SQLAlchemy откладывает загрузку столбца updated_at при использовании событий мапперов - PullRequest
0 голосов
/ 18 сентября 2018

У меня определена модель SQLAlchemy, которая содержит атрибут updated_at:

updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

У меня также есть пара событий сопоставления, определенных в модели:

@listens_for(Drive, 'after_insert')
def insert_listener(mapper, connect, self):
    from api.drive import operations
    operations.after_create(self)


@listens_for(Drive, 'after_update')
def update_listener(mapper, connect, self):
    from api.drive import operations
    operations.after_update(self)

Я загружаю модель как json в хранилище документов в подпрограммах after_create и after_update.

Я заметил, что SQLAlchemy не загружает атрибут update_at, если явно не запрашивается в подпрограммах after_*, и в результате отметка времени updated_at никогда не попадает в хранилище документов.Если я зарегистрирую model.updated_at прямо перед загрузкой объекта, он будет работать нормально.Я не настроил отложенную загрузку этого атрибута в определении модели, но SQLAlchemy, кажется, делает это под прикрытием.

1 Ответ

0 голосов
/ 18 сентября 2018

События after_insert и after_update предназначены для запуска дополнительных действий, когда сеанс сбрасывает временные объекты в базу данных.На этом этапе данные передаются в направлении one из Python в базу данных.Любые триггеры на стороне базы данных, такие как ваши значения по умолчанию, не видны на этом этапе, если только сервер явно не поддерживает возврат таких данных и вы не настроили SQLAlchemy для их получения в это время.

На всякий случай, если это не ясноfunc.now() - это правописание SQLAlchemy для функции NOW() в SQL, функция выполняется, когда база данных выполняет операторы INSERT или UPDATE, поэтому значение существует только на стороне базы данных.Это клиентские выражения SQL .

Вместо них следует использовать server_default и server_onupdate.Если вы используете базу данных, которая поддерживает функции RETURNING или OUTPUT inserted или аналогичные, для возврата значений выражений из вставок или обновлений непосредственно при выполнении (например, PostgreSQL, Oracle и SQL Server), то такие значения будут доступны для SQL-Алхимия немедленно.Для MySQL или SQLLite или других баз данных без поддержки RETURNING вы вынуждены обновить объект. См. Выборка сгенерированных сервером значений .

Для сервера, который поддерживает RETURNING Я думаю, что добавления eager_defaults должно быть достаточно:

class SomeModel(Base):
    updated_at = db.Column(
        db.DateTime,
        server_default=db.func.now(),
        server_onupdate=db.func.now()
    )

    __mapper_args__ = {"eager_defaults": True}

(Строка server_onupdate действительно означает, что SQLAlchemy будет знать, что нужно искать обновленное значение, и, вероятно, для работы требуется определение дополнительного триггераСм. эту проблему, где server_onupdate используется с MySQL ).

Даже если база данных не поддерживает RETURNING, использование eager_defaults должно работать, поскольку это автоматически добавитдополнительный SELECT к запросу. Это действительно стоит вам с точки зрения производительности .Попробуйте вместо этого использовать вызываемые Python для значений по умолчанию (и воздержитесь от того, чтобы база данных позаботилась об этих значениях).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...