You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PynamoDB使用save方法仅新增更新creation_datetime、每次更新修改last_update_datetime方案

解决方案

你遇到的问题核心是default_for_new仅在首次实例化模型且未给对应字段传值时生效,如果你是直接构造对象做upsert操作、或是实例化时未从数据库加载已有creation_datetime值就调用save,就会触发默认值重新生成,导致该字段被更新。可以用以下两种成熟方案实现需求:


方案1:重写抽象基类的save方法(兼容性最强,适配所有场景)

直接在你的抽象时间模型里重写save方法,自动判断对象是否为新建状态,对应更新时间字段:

from pynamodb.models import Model
from pynamodb.attributes import UTCDateTimeAttribute
from datetime import datetime

def current_datetime():
    return datetime.now()


class AbstractDateTimeModel(Model):
    creation_datetime = UTCDateTimeAttribute(null=True)
    last_update_datetime = UTCDateTimeAttribute(null=True)

    class Meta(object):
        abstract = True
        
    def save(self, *args, **kwargs):
        # 仅当对象不存在于数据库时才更新创建时间
        if not self.exists():
            self.creation_datetime = current_datetime()
        # 每次保存都更新最后修改时间
        self.last_update_datetime = current_datetime()
        return super().save(*args, **kwargs)

后续所有继承这个抽象类的模型,直接调用save()方法就会自动处理两个时间字段的更新逻辑,不需要额外写代码。


方案2:用update操作替代save(性能更高,适合更新场景)

如果是明确的更新场景,不要全量调用save方法,直接用PynamoDB的update接口指定要更新的字段,完全不会触碰creation_datetime字段:

# 先查询到要更新的对象
item = YourModel.get(hash_key="xxx", range_key="yyy")
# 仅更新指定字段和最后修改时间
item.update(actions=[
    YourModel.target_field.set("new_value"),
    YourModel.last_update_datetime.set(current_datetime())
])

这种方式不需要先全量加载对象属性再保存,也不会有字段误覆盖的风险,性能比重写save里调用exists()要高。


原写法适用场景说明

如果你每次更新对象的流程都是「先调用get从数据库拿到已有对象 -> 修改对应字段 -> 调用save」,那原来的写法本身不会有问题,因为get到的对象已经有creation_datetime的有效值,不会触发default_for_new的默认值生成逻辑,不会被覆盖。


内容的提问来源于stack exchange,提问作者suresh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 15:54:03