Ceci est mon modèle déclaratif:
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)
Cependant, lorsque j'essaie d'importer ce module, j'obtiens cette erreur:
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'
Si j'utilise un type Integer, je peux définir une valeur par défaut. Que se passe-t-il?
DateTime
n'a pas de clé par défaut en entrée. La clé par défaut doit être une entrée de la fonction Column
. Essaye ça:
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)
Pour des raisons de sécurité, vous souhaitez probablement que toutes les variables datetimes
soient calculées par votre serveur de base de données, plutôt que par le serveur d'applications. Le calcul de l'horodatage dans l'application peut poser des problèmes car la latence du réseau est variable, les clients subissent une dérive d'horloge légèrement différente et différents langages de programmation calculent parfois l'heure de manière légèrement différente.
SQLAlchemy vous permet de le faire en transmettant func.now()
ou func.current_timestamp()
(ce sont des alias les uns des autres) qui indique à la base de données de calculer l'horodatage lui-même.
server_default
de SQLALchemyDe plus, si vous indiquez déjà au DB de calculer la valeur par défaut, il est généralement préférable d'utiliser server_default
au lieu de default
. Cela indique à SQLAlchemy de transmettre la valeur par défaut dans le cadre de l'instruction CREATE TABLE
.
Par exemple, si vous écrivez un script ad hoc sur cette table, l'utilisation de server_default
signifie que vous n'aurez pas à vous inquiéter de l'ajout manuel d'un appel d'horodatage à votre script: la base de données le définira automatiquement.
onupdate
server_onupdate
de SQLAlchemySQLAlchemy prend également en charge onupdate
afin qu'à chaque fois que la ligne est mise à jour, elle insère un nouvel horodatage. Encore une fois, mieux vaut demander à la base de données de calculer l’horodatage lui-même:
from sqlalchemy.sql import func
time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())
Il existe un paramètre server_onupdate
, mais contrairement à server_default
, il ne définit en réalité rien du côté serveur. Cela indique simplement à SQLalchemy que votre base de données modifiera la colonne lorsqu'une mise à jour aura lieu (vous avez peut-être créé un déclencheur sur la colonne ), de sorte que SQLAlchemy demandera la valeur de retour afin de pouvoir mettre à jour l'objet correspondant.
Vous serez peut-être surpris de constater que, si vous apportez un grand nombre de modifications au sein d'une même transaction, elles ont toutes le même horodatage. En effet, le standard SQL spécifie que CURRENT_TIMESTAMP
renvoie des valeurs en fonction du début de la transaction.
PostgreSQL fournit les fonctions statement_timestamp()
et clock_timestamp()
non standard SQL que _/do modifient au sein d'une transaction. Docs here: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT
Si vous souhaitez utiliser les horodatages UTC, un bloc d'implémentation pour func.utcnow()
est fourni dans Documentation SQLAlchemy . Vous devez cependant fournir vous-même les fonctions appropriées spécifiques au pilote.
Vous pouvez également utiliser la fonction intégrée sqlalchemy pour DateTime par défaut
from sqlalchemy.sql import func
DT = Column(DateTime(timezone=True), default=func.now())
Le paramètre de mot clé default
doit être attribué à l'objet Column.
Exemple:
Column(u'timestamp', TIMESTAMP(timezone=True), primary_key=False, nullable=False, default=time_now),
La valeur par défaut peut être un appelable, ce que j'ai défini ici comme suit.
from pytz import timezone
from datetime import datetime
UTC = timezone('UTC')
def time_now():
return datetime.now(UTC)
[entrez la description du lien ici] [1]
Vous voudrez probablement utiliser onupdate = datetime.now pour que UPDATE modifie également le champ last_updated .
[1]: SQLAlchemy a deux valeurs par défaut pour les fonctions exécutées par python.
Selon la documentation de PostgreSQL, https://www.postgresql.org/docs/9.6/static/functions-datetime.html
now, CURRENT_TIMESTAMP, LOCALTIMESTAMP return the time of transaction.
Ceci est considéré comme une caractéristique: le but est d'autoriser un seul transaction d'avoir une notion cohérente de l'heure "actuelle", de sorte que plusieurs modifications dans la même transaction portent le même temps timbre.
Vous voudrez peut-être utiliser statement_timestamp ou clock_timestamp si vous ne voulez pas d'horodatage de transaction.
statement_timestamp ()
renvoie l'heure de début de l'instruction en cours (plus précisément, l'heure de réception du dernier message de commande du client) . statement_timestamp
clock_timestamp ()
renvoie l'heure actuelle et, par conséquent, sa valeur change même au sein d'une seule commande SQL.