python - current_timestamp - SQLAlchemy predeterminado DateTime
sqlalchemy datetime (6)
Calcule las marcas de tiempo dentro de su DB, no su cliente
Para la cordura, es probable que desee tener todas las datetimes
y datetimes
calculadas por su servidor de base de datos, en lugar del servidor de aplicaciones. El cálculo de la marca de tiempo en la aplicación puede provocar problemas porque la latencia de la red es variable, los clientes experimentan variaciones de reloj ligeramente diferentes, y los diferentes lenguajes de programación ocasionalmente calculan el tiempo de forma ligeramente diferente.
SQLAlchemy le permite hacer esto pasando func.now()
o func.now() (son alias uno del otro) que le dice al DB que calcule la marca de tiempo en sí.
Usar SQLALchemy''s server_default
Además, para un valor predeterminado donde ya le está diciendo al DB que calcule el valor, generalmente es mejor usar server_default
lugar de default
. Esto le dice a SQLAlchemy que pase el valor predeterminado como parte de la instrucción CREATE TABLE
.
Por ejemplo, si escribe una secuencia de comandos ad hoc en esta tabla, usar server_default
significa que no tendrá que preocuparse por agregar manualmente una marca de fecha y hora a su secuencia de comandos; la base de datos lo configurará automáticamente.
Comprender la onupdate
de SQLAlchemy / server_onupdate
SQLAlchemy también admite onupdate
para que cada vez que se actualice la fila inserte una nueva marca de tiempo. Nuevamente, es mejor decirle al DB que calcule la marca de tiempo en sí misma:
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 parámetro server_onupdate
, pero a diferencia de server_default
, en realidad no establece nada en el servidor. Simplemente le dice a SQLalchemy que su base de datos cambiará la columna cuando ocurra una actualización (quizás haya creado un activador en la columna ), por lo que SQLAlchemy le pedirá el valor de retorno para que pueda actualizar el objeto correspondiente.
Otro potencial gotcha:
Es posible que se sorprenda al notar que si realiza un montón de cambios en 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 proporciona el estándar de tiempo de statement_timestamp()
non-SQL statement_timestamp()
y clock_timestamp()
que 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, se proporciona un trozo de implementación para func.utcnow()
en la documentación de SQLAlchemy . Sin embargo, debe proporcionar las funciones específicas del controlador adecuadas por su cuenta.
Este es mi modelo declarativo:
import datetime
from sqlalchemy import Column, Integer
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 utilizo un tipo entero, puedo establecer un valor predeterminado. ¿Que esta pasando?
El parámetro de palabra clave default
debe asignarse al objeto Columna.
Ejemplo:
Column(u''timestamp'', TIMESTAMP(timezone=True), primary_key=False, nullable=False, default=time_now),
El valor predeterminado puede ser invocable, que aquí definí como el siguiente.
from pytz import timezone
from datetime import datetime
UTC = timezone(''UTC'')
def time_now():
return datetime.now(UTC)
Según la documentación de PostgreSQL, https://www.postgresql.org/docs/9.6/static/functions-datetime.html
now, CURRENT_TIMESTAMP, LOCALTIMESTAMP return the time of transaction.
Esto se considera una característica: la intención es permitir que una sola transacción tenga una noción coherente del tiempo "actual", de modo que las modificaciones múltiples dentro de la misma transacción tengan la misma marca de tiempo.
Es posible que desee utilizar statement_timestamp o clock_timestamp si no desea la marca de tiempo de la transacción.
statement_timestamp ()
devuelve la hora de inicio de la declaración actual (más específicamente, la hora de recepción del último mensaje de comando del cliente). statement_timestamp
clock_timestamp ()
devuelve la hora actual real, y por lo tanto su valor cambia incluso dentro de un solo comando SQL.
También puede usar la función sqlalchemy incorporada para DateTime por defecto
from sqlalchemy.sql import func
DT = Column(DateTime(timezone=True), default=func.now())
[ingrese la descripción del enlace aquí] [1]
Es probable que desee utilizar onupdate = datetime.now para que UPDATE también cambie el último campo actualizado .
[1]: SQLAlchemy tiene dos valores predeterminados para las funciones ejecutadas por Python.
- por defecto establece el valor en INSERT, solo una vez
- onupdate también establece el valor del resultado invocable en ACTUALIZAR.
DateTime
no tiene una clave predeterminada como entrada. La clave predeterminada debe ser una entrada a la función Column
. 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)