当更新同一模型中的另一个特定字段时,如何更新 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 关系?