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

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

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

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

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

谢谢!

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

【问题讨论】:

标签: django datetime django-models


【解决方案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-utilsFieldTracker。我将继续使用它,因为它使save() 期间更复杂的操作更容易。

      【讨论】:

      • 您能与我们分享一个例子吗?一旦你可以
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      相关资源
      最近更新 更多