Este é o meu 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)
No entanto, quando tento importar este módulo, recebo este erro:
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'
Se eu usar um tipo Inteiro, posso definir um valor padrão. O que está acontecendo?
python
date
sqlalchemy
Brandon O'Rourke
fonte
fonte
Respostas:
DateTime
não possui uma chave padrão como entrada. A tecla padrão deve ser uma entrada para aColumn
função. Tente o seguinte:fonte
datetime.datetime.utcnow
parece chamado como retorno de chamada.default=datetime.datetime.utcnow()
; você deseja passar autcnow
função, não o resultado da avaliação na carga do módulo.from sqlalchemy.sql import func; created_date = Column(DateTime(timezone=True), server_default=func.now()
Calcular carimbos de data e hora no seu banco de dados, não no seu cliente
Por questões de sanidade, você provavelmente deseja ter todos
datetimes
calculados pelo seu servidor de banco de dados, e não pelo servidor de aplicativos. O cálculo do registro de data e hora no aplicativo pode causar problemas, porque a latência da rede é variável, os clientes experimentam um desvio do relógio ligeiramente diferente e diferentes linguagens de programação ocasionalmente calculam o tempo de maneira ligeiramente diferente.SQLAlchemy permite que você faça isso passando
func.now()
oufunc.current_timestamp()
(eles são aliases um do outro) que informa ao banco de dados para calcular o próprio carimbo de data / hora.Use SQLALchemy
server_default
Além disso, para um padrão em que você já está dizendo ao banco de dados para calcular o valor, geralmente é melhor usá-lo em
server_default
vez dedefault
. Isso informa ao SQLAlchemy para passar o valor padrão como parte daCREATE TABLE
instrução.Por exemplo, se você escrever um script ad hoc nessa tabela, usar
server_default
significa que não precisará se preocupar em adicionar manualmente uma chamada de carimbo de data / hora ao seu script - o banco de dados o definirá automaticamente.Noções básicas sobre SQLAlchemy
onupdate
/server_onupdate
O SQLAlchemy também suporta,
onupdate
para que, sempre que a linha for atualizada, ele insira um novo carimbo de data / hora. Novamente, é melhor dizer ao banco de dados para calcular o próprio carimbo de data / hora:Existe um
server_onupdate
parâmetro, mas, ao contrárioserver_default
, ele não define nada no servidor. Apenas informa ao SQLalchemy que seu banco de dados alterará a coluna quando uma atualização acontecer (talvez você tenha criado um gatilho na coluna ); portanto, o SQLAlchemy solicitará o valor de retorno para que ele possa atualizar o objeto correspondente.Uma outra pegada em potencial:
Você pode se surpreender ao perceber que, se você fizer várias alterações em uma única transação, todas elas terão o mesmo carimbo de data / hora. Isso ocorre porque o padrão SQL especifica que
CURRENT_TIMESTAMP
retorna valores com base no início da transação.PostgreSQL fornece o não-SQL-padrão
statement_timestamp()
eclock_timestamp()
que fazer a mudança dentro de uma transação. Documentos aqui: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENTRegistro de data e hora UTC
Se você deseja usar registros de data e hora UTC,
func.utcnow()
é fornecido um stub de implementação na documentação do SQLAlchemy . Você precisa fornecer as funções específicas do driver apropriadas por conta própria.fonte
server_default=func.now()
trabalhou para mim, masonupdate=func.now()
não. Tenteionupdate=datetime.datetime.utcnow
(sem parênteses), que também não ajudouVocê também pode usar a função interna sqlalchemy por padrão
DateTime
fonte
server_default
vez dedefault
, o valor será tratado pelo próprio banco de dados.timezone=True
faz?Você provavelmente deseja usar
onupdate=datetime.now
para que UPDATEs também alterem olast_updated
campo.SQLAlchemy possui dois padrões para funções executadas em python.
default
define o valor em INSERT, apenas uma vezonupdate
define o valor para o resultado que pode ser chamado em UPDATE também.fonte
onupdate
, não faz nada por mim.created_at = db.Column(db.DateTime, server_default=UtcNow())
eupdated_at = db.Column(db.DateTime, server_default=UtcNow(), onupdate=UtcNow())
ondeUtcNow
é uma classe comoclass UtcNow(expression.FunctionElement): type = DateTime()
e nós temos@compiles(UtcNow, 'postgresql') def pg_utc_now(element, compiler, **kw): return "TIMEZONE('utc', CURRENT_TIMESTAMP)"
O
default
parâmetro keyword deve ser fornecido ao objeto Column.Exemplo:
O valor padrão pode ser exigível, que aqui defini da seguinte maneira.
fonte
time_now
vem?datetime.datetime.utcnow
De acordo com a documentação do PostgreSQL, https://www.postgresql.org/docs/9.6/static/functions-datetime.html
Você pode usar statement_timestamp ou clock_timestamp se não desejar o carimbo de data / hora da transação.
statement_timestamp ()
clock_timestamp ()
fonte