Dies ist mein deklaratives Modell:
import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Test(Base):
__tablename__ = 'test'
id = Column(Integer, primary_key=True)
created_date = DateTime(default=datetime.datetime.utcnow)
Wenn ich jedoch versuche, dieses Modul zu importieren, wird folgende Fehlermeldung angezeigt:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "orm/models2.py", line 37, in <module>
class Test(Base):
File "orm/models2.py", line 41, in Test
created_date = sqlalchemy.DateTime(default=datetime.datetime.utcnow)
TypeError: __init__() got an unexpected keyword argument 'default'
Wenn ich einen Integer-Typ verwende, kann ich einen Standardwert festlegen. Was ist los?
python
date
sqlalchemy
Brandon O'Rourke
quelle
quelle
Antworten:
DateTime
hat keinen Standardschlüssel als Eingabe. Die Standardtaste sollte eine Eingabe für dieColumn
Funktion sein. Versuche dies:quelle
datetime.datetime.utcnow
scheint als Rückruf bezeichnet.default=datetime.datetime.utcnow()
; Sie möchten dieutcnow
Funktion übergeben, nicht das Ergebnis der Auswertung bei Modullast.from sqlalchemy.sql import func; created_date = Column(DateTime(timezone=True), server_default=func.now()
Berechnen Sie Zeitstempel in Ihrer Datenbank, nicht in Ihrem Client
Aus Gründen der Vernunft möchten Sie wahrscheinlich, dass alle
datetimes
Daten von Ihrem DB-Server und nicht vom Anwendungsserver berechnet werden. Das Berechnen des Zeitstempels in der Anwendung kann zu Problemen führen, da die Netzwerklatenz variabel ist, Clients eine geringfügig unterschiedliche Taktdrift aufweisen und verschiedene Programmiersprachen gelegentlich die Zeit geringfügig unterschiedlich berechnen.Mit SQLAlchemy können Sie dies tun, indem Sie
func.now()
oderfunc.current_timestamp()
(sie sind Aliase voneinander) übergeben, wodurch die DB angewiesen wird, den Zeitstempel selbst zu berechnen.Verwenden Sie SQLALchemy's
server_default
Darüber hinaus ist es für einen Standard, bei dem Sie der Datenbank bereits anweisen, den Wert zu berechnen, im Allgemeinen besser, ihn
server_default
anstelle von zu verwendendefault
. Dies weist SQLAlchemy an, den Standardwert als Teil derCREATE TABLE
Anweisung zu übergeben.Wenn Sie beispielsweise ein Ad-hoc-Skript für diese Tabelle schreiben,
server_default
bedeutet dies, dass Sie sich nicht um das manuelle Hinzufügen eines Zeitstempelaufrufs zu Ihrem Skript kümmern müssen. Die Datenbank legt dies automatisch fest.SQLAlchemy verstehen
onupdate
/server_onupdate
SQLAlchemy unterstützt auch
onupdate
, dass bei jeder Aktualisierung der Zeile ein neuer Zeitstempel eingefügt wird. Auch hier ist es am besten, die DB anzuweisen, den Zeitstempel selbst zu berechnen:Es gibt einen
server_onupdate
Parameter, der jedoch im Gegensatzserver_default
dazu nichts Serverseitiges festlegt. Es teilt SQLalchemy lediglich mit, dass Ihre Datenbank die Spalte ändert, wenn eine Aktualisierung erfolgt (möglicherweise haben Sie einen Auslöser für die Spalte erstellt ), sodass SQLAlchemy nach dem Rückgabewert fragt, damit das entsprechende Objekt aktualisiert werden kann.Ein weiteres mögliches Problem:
Es könnte Sie überraschen, dass alle Änderungen innerhalb einer einzelnen Transaktion denselben Zeitstempel haben. Dies liegt daran, dass der SQL-Standard angibt, dass
CURRENT_TIMESTAMP
Werte basierend auf dem Start der Transaktion zurückgegeben werden.PostgreSQL bietet den Nicht-SQL-Standard
statement_timestamp()
undclock_timestamp()
das tut Änderung innerhalb einer Transaktion. Dokumente hier: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENTUTC-Zeitstempel
Wenn Sie UTC-Zeitstempel verwenden möchten, finden Sie
func.utcnow()
in der SQLAlchemy-Dokumentation einen Implementierungsstub für . Sie müssen jedoch selbst geeignete treiberspezifische Funktionen bereitstellen.quelle
server_default=func.now()
arbeitete für mich,onupdate=func.now()
tat es aber nicht. Versuchtonupdate=datetime.datetime.utcnow
(ohne Klammern), das hat auch nicht geholfenSie können standardmäßig auch die integrierte Funktion sqlalchemy verwenden
DateTime
quelle
server_default
stattdessen auch einendefault
Wert verwenden, der von der Datenbank selbst verarbeitet wird.timezone=True
dasSie möchten wahrscheinlich verwenden,
onupdate=datetime.now
damit UPDATEs auch daslast_updated
Feld ändern .SQLAlchemy hat zwei Standardeinstellungen für von Python ausgeführte Funktionen.
default
Setzt den Wert auf INSERT nur einmalonupdate
Setzt den Wert auch bei UPDATE auf das aufrufbare Ergebnis.quelle
onupdate
tut es nichts für mich.created_at = db.Column(db.DateTime, server_default=UtcNow())
undupdated_at = db.Column(db.DateTime, server_default=UtcNow(), onupdate=UtcNow())
woUtcNow
ist eine Klasse wieclass UtcNow(expression.FunctionElement): type = DateTime()
und wir haben@compiles(UtcNow, 'postgresql') def pg_utc_now(element, compiler, **kw): return "TIMEZONE('utc', CURRENT_TIMESTAMP)"
Der
default
Schlüsselwortparameter sollte dem Column-Objekt zugewiesen werden.Beispiel:
Der Standardwert kann ein aufrufbarer Wert sein, den ich hier wie folgt definiert habe.
quelle
time_now
das?datetime.datetime.utcnow
Gemäß der PostgreSQL-Dokumentation https://www.postgresql.org/docs/9.6/static/functions-datetime.html
Möglicherweise möchten Sie den Anweisungstimestamp oder den Uhrzeitstempel verwenden, wenn Sie keinen Transaktionszeitstempel möchten.
statement_timestamp ()
clock_timestamp ()
quelle