当更新同一模型中的另一个特定字段时,如何更新 Django models.DateTimeField?

Posted

技术标签:

【中文标题】当更新同一模型中的另一个特定字段时,如何更新 Django models.DateTimeField?【英文标题】:How can I update a Django models.DateTimeField when another, specific field in the same model is updated? 【发布时间】:2016-10-18 10:59:48 【问题描述】:

我在这里的模型中有两个字段:

is_active = models.BooleanField(default=False)
active_from = models.DateTimeField(blank=True)

is_active 设置为True 时,我希望将active_from 更新为当前日期时间。

我该怎么做呢?如果在一个字段中也有一种更简洁的方法,我愿意接受其他选择。

谢谢!

编辑:我想将它包含在模型中以保持封装。这将是 API 的一部分。

【问题讨论】:

使用pre_save 信号可能好吗? docs.djangoproject.com/en/1.9/ref/signals/#pre-save 这是基于它的答案:***.com/questions/1355150/… 虽然可以使用信号,但根据 Django 的两个勺子,将它们仅用作最后手段被认为是最佳实践。仅供参考。 没听说过——是Django项目开发者写的吗? 【参考方案1】:

一种方法是在您的自定义模型上定义一个save() 方法,以寻找is_active 中的更改。没有简单的方法来实现这一点:您需要通过定义自定义__init__ 方法手动保存is_active 值的先前状态。它可能看起来像这样:

class MyModel(models.Model):
    is_active = models.BooleanField(default=False)
    active_from = models.DateTimeField(blank=True)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__is_active = self.active

    def save(self, *args, **kwargs):
        if self.is_active and not self.__is_active:
            self.active_from = datetime.now()
        super().save(*args, **kwargs)

This question 有一些答案可能会有所帮助。

【讨论】:

if self.is_active and not self.__is_active 检查什么?我不知道__ 有什么变化 self.__is_active 是应用更改之前模型的值,如__init__ 方法中设置的那样。检查的基本意思是:如果 is_active 现在是 True,之前是 False,更新 active_from 这个答案比我的好。【参考方案2】:

这是我到目前为止拼凑起来的。这似乎是最 Django 式的做法,但如果不是,我很高兴得到纠正。

from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver
import datetime

class MyModel(models.Model):
    is_active = models.BooleanField(default=False)
    active_from = models.DateTimeField(blank=True)

# Set active_from if active is set in an update
@receiver(pre_save, sender=MyModel)
def set_active_from_on_update(sender, instance, update_fields, **kwargs):
    if 'is_active' in update_fields and instance.is_active is True:
            instance.active_from = datetime.now()

# Set active_from if active is set on create
@receiver(post_save, sender=MyModel)
def set_active_from_on_create(sender, instance, created, **kwargs):
    if created and instance.is_active is True:
        instance.active_from = datetime.now()

我的推理:pre_save 中的update_fields 似乎是基于特定字段更新的任何逻辑的正确位置,但pre_save 不知道instance 是否会成为数据库中的新条目,所以post_save 需要使用create 布尔值。

我想我也可以取消is_active 并将active_from 设置为null,当它不活动时,但这似乎并不安全。

【讨论】:

【参考方案3】:

当您切换is_active 时,同时更新active_from

例如:

def toggle_user_active_and_update(request, *a, **kw):
    request.user.is_active = !request.user.is_active
    request.user.active_from = datetime.datetime.now()
    request.user.save()

【讨论】:

【参考方案4】:

另一种选择是来自django-model-utils 的FieldTracker。我将继续使用它,因为它使save() 期间更复杂的操作更容易。

【讨论】:

您能与我们分享一个例子吗?一旦你可以

以上是关于当更新同一模型中的另一个特定字段时,如何更新 Django models.DateTimeField?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据具有外键关系的另一个模型更新 Django 模型的字段

如何使用 AJAX 更新 simple_form 输入字段?

当同一模型也存在 HasMany 关系时,如何更新 HasOne 关系?

当同一转发器字段的值以其他语言更新时,ACF 转发器字段中的值是不是为空?

如何使用猫鼬复制字段数据并在同一文档的另一个字段中使用它?

当前日期与特定日期相同时如何自动更新字段