it-swarm.com.de

SQLAlchemy-Standardeinstellung DateTime

Dies ist mein deklaratives Modell:

import datetime
from sqlalchemy import Column, Integer
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Test(Base):
    __table= 'test'

    id = Column(Integer, primary_key=True)
    created_date = DateTime(default=datetime.datetime.utcnow)

Wenn ich jedoch versuche, dieses Modul zu importieren, erhalte ich folgende Fehlermeldung:

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?

98

DateTime hat keinen Standardschlüssel als Eingabe. Der Standardschlüssel sollte eine Eingabe für die Funktion Column sein. Versuche dies:

import datetime
from sqlalchemy import Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Test(Base):
    __table= 'test'

    id = Column(Integer, primary_key=True)
    created_date = Column(DateTime, default=datetime.datetime.utcnow)
130
PearsonArtPhoto

Berechnen Sie Zeitstempel in Ihrer Datenbank, nicht in Ihrem Kunden

Aus Gründen der Vernunft möchten Sie wahrscheinlich, dass alle datetimes von Ihrem DB-Server berechnet werden und nicht vom Anwendungsserver. Das Berechnen des Zeitstempels in der Anwendung kann zu Problemen führen, da die Netzwerklatenz variabel ist, Clients eine geringfügig unterschiedliche Zeitverschiebung aufweisen und verschiedene Programmiersprachen die Zeit gelegentlich geringfügig unterschiedlich berechnen.

Mit SQLAlchemy können Sie dies tun, indem Sie func.now() oder func.current_timestamp() (sie sind Aliase voneinander) übergeben, was der DB mitteilt, zu Berechnen Sie den Zeitstempel selbst.

Verwenden Sie SQLALchemys server_default

Bei einer Standardeinstellung, bei der Sie der Datenbank bereits mitteilen, dass sie den Wert berechnen soll, ist es im Allgemeinen besser, server_default anstelle von default zu verwenden. Dadurch wird SQLAlchemy angewiesen, den Standardwert als Teil der Anweisung CREATE TABLE Zu übergeben.

Wenn Sie beispielsweise ein Ad-hoc-Skript für diese Tabelle schreiben und server_default Verwenden, müssen Sie sich nicht um das manuelle Hinzufügen eines Zeitstempelaufrufs zu Ihrem Skript kümmern. Die Datenbank legt diesen automatisch fest.

Grundlegendes zu SQLAlchemys onupdate/server_onupdate

SQLAlchemy unterstützt auch onupdate, sodass bei jeder Aktualisierung der Zeile ein neuer Zeitstempel eingefügt wird. Auch hier empfiehlt es sich, die Datenbank anzuweisen, den Zeitstempel selbst zu berechnen:

from sqlalchemy.sql import func

time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())

Es gibt einen server_onupdate - Parameter, der jedoch im Gegensatz zu server_default Nichts auf dem Server festlegt. Es teilt SQLalchemy lediglich mit, dass Ihre Datenbank die Spalte ändert, wenn ein Update stattfindet (möglicherweise haben Sie ein Auslöser für die Spalte erstellt), sodass SQLAlchemy nach dem Rückgabewert fragt, damit das entsprechende Objekt aktualisiert werden kann.

Ein weiteres potenzielles gotcha:

Es könnte Sie überraschen, zu bemerken, dass alle Änderungen, die Sie innerhalb einer einzelnen Transaktion vornehmen, denselben Zeitstempel haben. Dies liegt daran, dass der SQL-Standard festlegt, dass CURRENT_TIMESTAMP Werte basierend auf dem Start der Transaktion zurückgibt.

PostgreSQL bietet den Nicht-SQL-Standard statement_timestamp() und clock_timestamp(), die innerhalb einer Transaktion ändern . Dokumente hier: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT

UTC-Zeitstempel

Wenn Sie UTC-Zeitstempel verwenden möchten, finden Sie einen Implementierungsstumpf für func.utcnow() in SQLAlchemy-Dokumentation . Sie müssen jedoch selbst geeignete treiberspezifische Funktionen bereitstellen.

276
Jeff Widman

Sie können auch die eingebaute Funktion sqlalchemy für die Standardeinstellung DateTime verwenden

from sqlalchemy.sql import func

DT = Column(DateTime(timezone=True), default=func.now())
45
qwerty

Der default-Schlüsselwortparameter sollte dem Column-Objekt übergeben werden.

Beispiel:

Column(u'timestamp', TIMESTAMP(timezone=True), primary_key=False, nullable=False, default=time_now),

Der Standardwert kann ein aufrufbarer Wert sein, den ich hier wie folgt definiert habe.

from pytz import timezone
from datetime import datetime

UTC = timezone('UTC')

def time_now():
    return datetime.now(UTC)
5
Keith

[Linkbeschreibung hier eingeben] [1]

Wahrscheinlich möchten Sie onupdate = datetime.now verwenden, damit UPDATEs auch das last_updated - Feld ändern.

[1]: SQLAlchemy hat zwei Standardeinstellungen für von Python ausgeführte Funktionen.

  • default setzt den Wert für INSERT nur einmal
  • onupdate setzt den Wert auch beim UPDATE auf das Ergebnis callable.
4
user3389572

Wie in der PostgreSQL-Dokumentation beschrieben: https://www.postgresql.org/docs/9.6/static/functions-datetime.html

now, CURRENT_TIMESTAMP, LOCALTIMESTAMP return the time of transaction.

Dies wird als eine Funktion betrachtet: Die Absicht ist es, ein einzelnes .__ zuzulassen. Transaktion, um eine konsistente Vorstellung von der "aktuellen" Zeit zu haben, so dass Mehrere Modifikationen innerhalb einer Transaktion haben dieselbe Zeit Briefmarke.

Sie können statement_timestamp oder clock_timestamp verwenden, wenn Sie keinen Transaktionszeitstempel wünschen. 

statement_timestamp () 

gibt die Startzeit der aktuellen Anweisung zurück (insbesondere .__ die Uhrzeit des Empfangs der letzten Befehlsnachricht vom Client) . statement_timestamp

clock_timestamp () 

gibt die aktuelle Uhrzeit zurück, und daher ändert sich ihr Wert sogar innerhalb eines einzigen SQL-Befehls.

0
abhi shukla