SQLAlchemy по умолчанию DateTime

Это моя декларативная модель:

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) 

Однако, когда я пытаюсь импортировать этот модуль, я получаю эту ошибку:

 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, я могу установить значение по умолчанию. Что происходит?

DateTime не имеет ключа по умолчанию в качестве входа. Клавиша по умолчанию должна быть введена в функцию Column . Попробуй это:

 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) 

Вычислить временные метки в вашей БД, а не ваш клиент

Для здравомыслия вы, вероятно, хотите, чтобы все данные datetimes вычислялись вашим сервером БД, а не сервером приложений. Вычисление временной отметки в приложении может привести к проблемам, поскольку задержка между сетями является переменной, клиенты испытывают несколько иной сдвиг часов, а разные языки программирования иногда вычисляют время несколько иначе.

SQLAlchemy позволяет это сделать, передав func.now() или func.current_timestamp() (они являются псевдонимами друг друга), которые func.current_timestamp() БД для вычисления самой метки времени.

Использовать server_default server_default

Кроме того, по умолчанию, когда вы уже сообщаете БД для вычисления значения, обычно лучше использовать server_default а не по default . Это говорит SQLAlchemy передать значение по умолчанию как часть инструкции CREATE TABLE .

Например, если вы пишете ad hoc-скрипт в этой таблице, использование server_default означает, что вам не нужно беспокоиться о том, чтобы вручную добавить вызов timestamp к вашему сценарию – база данных будет устанавливать его автоматически.

Общие сведения о onupdate / server_onupdate

SQLAlchemy также поддерживает onupdate так что в любое время, когда строка обновляется, она вставляет новую метку времени. Опять же, лучше сказать БД для вычисления самой метки:

 from sqlalchemy.sql import func time_created = Column(DateTime(timezone=True), server_default=func.now()) time_updated = Column(DateTime(timezone=True), onupdate=func.now()) 

Существует параметр server_onupdate , но в отличие от server_default он фактически не устанавливает ничего серверного. Он просто говорит SQLalchemy, что ваша база данных изменит столбец при обновлении (возможно, вы создали триггер в столбце ), поэтому SQLAlchemy будет запрашивать возвращаемое значение, чтобы он мог обновлять соответствующий объект.

Еще один потенциальный вопрос:

Вы можете быть удивлены, заметив, что если вы сделаете кучу изменений в рамках одной транзакции, все они имеют одну и ту же метку времени. Это потому, что стандарт SQL указывает, что CURRENT_TIMESTAMP возвращает значения в зависимости от начала транзакции.

PostgreSQL предоставляет не-SQL-standard statement_timestamp() и clock_timestamp() которые изменяются внутри транзакции. Документы здесь: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT

Временная метка UTC

Если вы хотите использовать отметки времени UTC, в документации SQLAlchemy предоставляется заглушка реализации для func.utcnow() . Однако вам необходимо предоставить соответствующие функции, связанные с драйвером.

Вы также можете использовать встроенную функцию sqlalchemy по умолчанию DateTime

 from sqlalchemy.sql import func DT = Column(DateTime(timezone=True), default=func.now()) 

Параметр ключевого слова по default должен быть присвоен объекту Column.

Пример:

 Column(u'timestamp', TIMESTAMP(timezone=True), primary_key=False, nullable=False, default=time_now), 

Значение по умолчанию может быть вызываемым, которое здесь определяется следующим образом.

 from pytz import timezone from datetime import datetime UTC = timezone('UTC') def time_now(): return datetime.now(UTC) 

[введите ссылку здесь] [1]

Вероятно, вы захотите использовать onupdate = datetime.now, чтобы UPDATE также изменили поле last_updated .

[1]: SQLAlchemy имеет два значения по умолчанию для исполняемых функций на основе python.

  • default устанавливает значение INSERT только один раз
  • onupdate устанавливает значение для вызываемого результата в UPDATE.