Fecha y hora predeterminada de SQLAlchemy

Resuelto Brandon O'Rourke asked hace 12 años • 13 respuestas

Este es mi modelo declarativo:

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)

Sin embargo, cuando intento importar este módulo, aparece este error:

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 uso un tipo Entero, puedo establecer un valor predeterminado. ¿Qué está sucediendo?

Brandon O'Rourke avatar Nov 14 '12 05:11 Brandon O'Rourke
Aceptado

Calcule marcas de tiempo dentro de su base de datos, no de su cliente

Por razones de cordura, probablemente desee datetimesque su servidor de base de datos calcule todo, en lugar del servidor de aplicaciones. Calcular la marca de tiempo en la aplicación puede generar problemas porque la latencia de la red es variable, los clientes experimentan una desviación del reloj ligeramente diferente y, en ocasiones, diferentes lenguajes de programación calculan el tiempo de manera ligeramente diferente.

SQLAlchemy le permite hacer esto pasando func.now()o func.current_timestamp()(son alias entre sí) que le dice a la base de datos que calcule la marca de tiempo.

Utilice SQLALchemyserver_default

Además, para un valor predeterminado en el que ya le está indicando a la base de datos que calcule el valor, generalmente es mejor usarlo server_defaulten lugar de default. Esto le dice a SQLAlchemy que pase el valor predeterminado como parte de la CREATE TABLEdeclaración.

Por ejemplo, si escribe un script ad hoc en esta tabla, usar server_defaultsignifica que no tendrá que preocuparse por agregar manualmente una llamada de marca de tiempo a su script: la base de datos la configurará automáticamente.

Entendiendo SQLAlchemy onupdate/server_onupdate

SQLAlchemy también admite onupdateque cada vez que se actualice la fila se inserte una nueva marca de tiempo. Nuevamente, es mejor decirle a la base de datos que calcule la marca de tiempo:

from sqlalchemy.sql import func

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

Hay un server_onupdateparámetro, pero a diferencia de server_default, en realidad no establece nada en el lado del servidor. Simplemente le dice a SQLalchemy que su base de datos cambiará la columna cuando ocurra una actualización (tal vez creó un disparador en la columna ), por lo que SQLAlchemy le pedirá el valor de retorno para poder actualizar el objeto correspondiente.

Otro problema potencial:

Te sorprenderá notar que si realizas muchos cambios en una sola transacción, todos tendrán la misma marca de tiempo. Esto se debe a que el estándar SQL especifica que CURRENT_TIMESTAMPdevuelve valores basados ​​en el inicio de la transacción.

PostgreSQL proporciona el estándar no SQL statement_timestamp()y clock_timestamp()cuáles cambian dentro de una transacción. Documentos aquí: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT

marca de tiempo UTC

Si desea utilizar marcas de tiempo UTC, func.utcnow()se proporciona un fragmento de implementación en la documentación de SQLAlchemy . Sin embargo, debe proporcionar usted mismo las funciones específicas del controlador adecuadas.

Jeff Widman avatar Nov 04 '2015 21:11 Jeff Widman

DateTimeno tiene una clave predeterminada como entrada. La clave predeterminada debe ser una entrada a la Columnfunción. Prueba esto:

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 = Column(DateTime, default=datetime.datetime.utcnow)
PearsonArtPhoto avatar Nov 13 '2012 23:11 PearsonArtPhoto

También puede usar la función incorporada sqlalchemy por defectoDateTime

from sqlalchemy.sql import func

DT = Column(DateTime(timezone=True), default=func.now())
qwerty avatar May 06 '2015 17:05 qwerty