Это моя декларативная модель:
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)
Однако, когда я пытаюсь импортировать этот модуль, я получаю эту ошибку:
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'
Если я использую тип Integer, я могу установить значение по умолчанию. В чем дело?
python
date
sqlalchemy
Брэндон О'Рурк
источник
источник
Ответы:
DateTime
не имеет ключа по умолчанию в качестве ввода. Ключ по умолчанию должен быть вводом дляColumn
функции. Попробуй это:источник
datetime.datetime.utcnow
кажется, называется обратным вызовом.default=datetime.datetime.utcnow()
; Вы хотите передатьutcnow
функцию, а не результат ее оценки при загрузке модуля.from sqlalchemy.sql import func; created_date = Column(DateTime(timezone=True), server_default=func.now()
Вычислять метки времени в вашей БД, а не в вашем клиенте
Для здравомыслия, вы, вероятно, хотите, чтобы все
datetimes
вычислялись вашим сервером БД, а не сервером приложений. Вычисление метки времени в приложении может привести к проблемам, поскольку задержка в сети является переменной, клиенты испытывают несколько различный сдвиг тактовой частоты, а разные языки программирования иногда вычисляют время немного по-разному.SQLAlchemy позволяет вам сделать это, передав
func.now()
илиfunc.current_timestamp()
(они являются псевдонимами друг друга), который указывает БД рассчитать саму метку времени.Используйте SQLALchemy's
server_default
Кроме того, для значения по умолчанию, когда вы уже говорите БД для вычисления значения, обычно лучше использовать
server_default
вместоdefault
. Это говорит SQLAlchemy передать значение по умолчанию как частьCREATE TABLE
инструкции.Например, если вы напишите специальный скрипт для этой таблицы, используя
server_default
означает, что вам не нужно беспокоиться о ручном добавлении вызова метки времени в ваш скрипт - база данных установит его автоматически.Понимание SQLAlchemy's
onupdate
/server_onupdate
SQLAlchemy также поддерживает,
onupdate
так что при каждом обновлении строки вставляется новая отметка времени. Опять же, лучше всего сказать БД рассчитать саму метку времени:Есть
server_onupdate
параметр, но, в отличие от негоserver_default
, он ничего не устанавливает на стороне сервера. Он просто сообщает SQLalchemy, что ваша база данных изменит столбец при обновлении (возможно, вы создали триггер для столбца ), поэтому SQLAlchemy запросит возвращаемое значение, чтобы он мог обновить соответствующий объект.Еще один потенциальный вопрос:
Вы можете быть удивлены, заметив, что если вы сделаете кучу изменений в одной транзакции, они все будут иметь одну и ту же метку времени. Это потому, что стандарт SQL определяет, что
CURRENT_TIMESTAMP
возвращает значения в зависимости от начала транзакции.PostgreSQL предоставляет не-SQL стандарта
statement_timestamp()
иclock_timestamp()
которые делают изменения в рамках транзакции. Документы здесь: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENTМетка времени UTC
Если вы хотите использовать метки времени UTC, заглушка для реализации
func.utcnow()
предоставлена в документации SQLAlchemy . Вы должны предоставить соответствующие специфичные для драйвера функции самостоятельно, хотя.источник
server_default=func.now()
работал для меня, ноonupdate=func.now()
не сделал. Попробовалonupdate=datetime.datetime.utcnow
(без скобок), что тоже не помоглоВы также можете использовать встроенную функцию sqlalchemy по умолчанию
DateTime
источник
server_default
вместоdefault
этого значение, которое будет обрабатываться самой базой данных.timezone=True
?Вы, вероятно, хотите использовать
onupdate=datetime.now
так, чтобы ОБНОВЛЕНИЯ также изменилиlast_updated
поле.SQLAlchemy имеет два значения по умолчанию для функций, выполняемых на Python.
default
устанавливает значение на INSERT, только один разonupdate
также устанавливает значение для вызываемого результата в UPDATE.источник
onupdate
для меня ничего не делает.created_at = db.Column(db.DateTime, server_default=UtcNow())
иupdated_at = db.Column(db.DateTime, server_default=UtcNow(), onupdate=UtcNow())
гдеUtcNow
класс, какclass UtcNow(expression.FunctionElement): type = DateTime()
и у нас есть@compiles(UtcNow, 'postgresql') def pg_utc_now(element, compiler, **kw): return "TIMEZONE('utc', CURRENT_TIMESTAMP)"
Параметр
default
ключевого слова должен быть передан объекту Column.Пример:
Значением по умолчанию может быть вызываемое, которое здесь я определил следующим образом.
источник
time_now
берутся?datetime.datetime.utcnow
Согласно документации PostgreSQL, https://www.postgresql.org/docs/9.6/static/functions-datetime.html.
Вы можете использовать statement_timestamp или clock_timestamp , если вы не хотите транзакций метки времени.
statement_timestamp ()
clock_timestamp ()
источник