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. ¿Que esta pasando?
python
date
sqlalchemy
Brandon O'Rourke
fuente
fuente
Respuestas:
DateTime
no tiene una clave predeterminada como entrada. La tecla predeterminada debe ser una entrada a laColumn
función. Prueba esto:fuente
datetime.datetime.utcnow
parece llamado como devolución de llamada.default=datetime.datetime.utcnow()
; desea pasar lautcnow
función, no el resultado de evaluarla en la carga del módulo.from sqlalchemy.sql import func; created_date = Column(DateTime(timezone=True), server_default=func.now()
Calcule las marcas de tiempo dentro de su base de datos, no su cliente
Para la cordura, es probable que desee tener todo
datetimes
calculado por su servidor de base de datos, en lugar de por el servidor de aplicaciones. Calcular la marca de tiempo en la aplicación puede ocasionar problemas porque la latencia de la red es variable, los clientes experimentan una deriva del reloj ligeramente diferente, y diferentes lenguajes de programación ocasionalmente calculan el tiempo de manera ligeramente diferente.SQLAlchemy le permite hacer esto pasando
func.now()
ofunc.current_timestamp()
(son alias entre sí) que le dice a la base de datos que calcule la marca de tiempo.Use SQLALchemy's
server_default
Además, para un valor predeterminado en el que ya le está diciendo a la base de datos que calcule el valor, generalmente es mejor usarlo en
server_default
lugar de hacerlodefault
. Esto le dice a SQLAlchemy que pase el valor predeterminado como parte de laCREATE TABLE
declaración.Por ejemplo, si escribe un script ad hoc en esta tabla, usar
server_default
significa que no tendrá que preocuparse por agregar manualmente una llamada de marca de tiempo a su script; la base de datos lo configurará automáticamente.Comprensión de SQLAlchemy's
onupdate
/server_onupdate
SQLAlchemy también soporta
onupdate
de manera que en cualquier momento se actualiza la fila se inserta un nuevo orden de llegada. Nuevamente, es mejor decirle a la base de datos que calcule la marca de tiempo en sí:Hay un
server_onupdate
parámetro, pero a diferenciaserver_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 (quizás haya creado un disparador en la columna ), por lo que SQLAlchemy le pedirá el valor de retorno para que pueda actualizar el objeto correspondiente.Otro potencial problema:
Es posible que se sorprenda al notar que si realiza varios cambios dentro de una sola transacción, todos tienen la misma marca de tiempo. Esto se debe a que el estándar SQL especifica que
CURRENT_TIMESTAMP
devuelve valores basados en el inicio de la transacción.PostgreSQL ofrece la no-estándar SQL
statement_timestamp()
yclock_timestamp()
el que hacer el cambio dentro de una transacción. Documentos aquí: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENTMarca de tiempo UTC
Si desea utilizar las marcas de tiempo UTC, un cabo de aplicación para
func.utcnow()
se proporciona en la documentación SQLAlchemy . Sin embargo, debe proporcionar funciones específicas del controlador apropiadas por su cuenta.fuente
server_default=func.now()
funcionó para mí, peroonupdate=func.now()
no lo hizo. Probadoonupdate=datetime.datetime.utcnow
(sin corchetes), eso tampoco ayudóTambién puede usar la función incorporada sqlalchemy por defecto
DateTime
fuente
server_default
lugar dedefault
lo que el valor lo manejará la base de datos.timezone=True
hacer?Es probable que desee usar
onupdate=datetime.now
para que las ACTUALIZACIONES también cambien ellast_updated
campo.SQLAlchemy tiene dos valores predeterminados para las funciones ejecutadas por Python.
default
establece el valor en INSERT, solo una vezonupdate
también establece el valor en el resultado invocable en UPDATE.fuente
onupdate
no hace nada por mí.created_at = db.Column(db.DateTime, server_default=UtcNow())
yupdated_at = db.Column(db.DateTime, server_default=UtcNow(), onupdate=UtcNow())
dóndeUtcNow
es una clase comoclass UtcNow(expression.FunctionElement): type = DateTime()
y tenemos@compiles(UtcNow, 'postgresql') def pg_utc_now(element, compiler, **kw): return "TIMEZONE('utc', CURRENT_TIMESTAMP)"
El
default
parámetro de palabra clave debe darse al objeto Column.Ejemplo:
El valor predeterminado puede ser invocable, que aquí definí como el siguiente.
fuente
time_now
vienedatetime.datetime.utcnow
Según la documentación de PostgreSQL, https://www.postgresql.org/docs/9.6/static/functions-datetime.html
Es posible que desee utilizar la declaración de fecha y hora o la hora de reloj si no desea la marca de tiempo de la transacción.
Statement_timestamp ()
clock_timestamp ()
fuente