在peewee中是否有类似于MySQL中TimeStamp的DateTimeField自动更新选项?

24
我希望您可以在记录每次修改时更新时间戳字段,就像在MySQL中一样。使用DateTimeField(default=datetime.datetime.now())只会在第一次创建时设置它...有没有简单的解决方案?难道唯一的解决方案是在MySQL数据库中手动设置列选项吗?
4个回答

39

您可以在您的模型类上覆盖save方法。

class Something(Model):
    created = DateTimeField(default=datetime.datetime.now)
    modified = DateTimeField

    def save(self, *args, **kwargs):
        self.modified = datetime.datetime.now()
        return super(Something, self).save(*args, **kwargs)

1
请指导如何进行更新操作,例如:Something.update(othercolumn=foo).where(id=2).execute()。还是说我需要重写代码使用Model.save()呢?提前感谢您的帮助。 - chrisinmtown
2
如果您正在调用.update(),那么您可能需要在SQL端实现时间戳更新逻辑。update()不会调用save() - coleifer
有没有一种方法可以在Peewee中覆盖Model类? - Jeff
1
Jeff,Peewee的模型只是普通的类。你可以对它们进行子类化(例如创建一个带有各种默认字段、辅助函数等的BaseModel)。 - Shayne

4

只需在MySQL中使用TIMESTAMP类型。每当行更新时,该字段将自动更新。

model中:

last_updated = peewee.TimestampField()

有没有关于如何在Postgresql中实现这个的技巧? - Kyrremann
这是不正确的。这将在创建时存储当前的UTC时间戳,但不会在行被修改时更新它(除非您定义了一个ON UPDATE约束)。 - booshong

1
from datetime import datetime

from peewee import (AutoField, CharField, DateTimeField, FloatField,
                    IntegerField, Model, MySQLDatabase, TextField, SQL)

from config import DataBaseConfig

mysql_client = MySQLDatabase(
    "your_database_name",
    host=DataBaseConfig.host,
    port=DataBaseConfig.port,
    user=DataBaseConfig.user,
    password=DataBaseConfig.password,
)

class CommonModel(Model):
    id = AutoField(verbose_name="primary key")
    create_time = DateTimeField(default=datetime.now, verbose_name="create time")
    update_time = DateTimeField(default=datetime.now, verbose_name="update time", constraints=[SQL('ON UPDATE CURRENT_TIMESTAMP')])

    class Meta:
        database = mysql_client

你可以参考这篇文档。单列索引和约束

1

您也可以重写update方法来提供功能。就像Coleifer所做的那样:

class Something(Model):
    created = DateTimeField(default=datetime.datetime.now)
    modified = DateTimeField

    @classmethod
    def update(cls, *args, **kwargs):
        kwargs['modified'] = datetime.datetime.now()
        return super(Something, cls).save(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.modified = datetime.datetime.now()
        return super(Something, self).save(*args, **kwargs)

您也可以在replace方法上执行相同的操作。


不好的想法。SQL生成方法永远不应该被覆盖(更新,插入,选择等)。 - coleifer
我认为,如果逻辑足够复杂,将其添加到“预保存”步骤中是可以接受的。您只需要确保在CRUD对象时强制使用正确的方法(例如,应避免使用update()delete())。 - booshong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接