[英]Check previous model value on save
I have a model that saves an Excursion.我有一个 model 可以节省一次游览。 The user can change this excursion, but I need to know what the excursion was before he change it, because I keep track of how many "bookings" are made per excursion, and if you change your excursion, I need to remove one booking from the previous excursion.
用户可以更改此短途旅行,但我需要在他更改之前知道短途旅行是什么,因为我会跟踪每次短途旅行的“预订”数量,如果您更改短途旅行,我需要从中删除一个预订上一次游览。
Im not entirely sure how this should be done.我不完全确定应该怎么做。
Im guessing you use a signal for this?我猜你为此使用信号?
Should I use pre_save, pre_init or what would be the best for this?我应该使用 pre_save、pre_init 还是最好的方法?
pre_save is not the correct one it seems, as it prints the new values, not the "old value" as I expected pre_save 似乎不是正确的,因为它打印的是新值,而不是我预期的“旧值”
@receiver(pre_save, sender=Delegate)
def my_callback(sender, instance, *args, **kwargs):
print instance.excursion
Do you have several options.你有几个选择。
First one is to overwrite save method :第一个是覆盖保存方法:
#Delegate
def save(self, *args, **kwargs):
if self.pk:
previous_excursion = Delegate.objects.get(self.pk).excursion
super(Model, self).save(*args, **kwargs)
if self.pk and self.excursion != previous_excursion:
#change booking
Second one is binding function to post save signal + django model utils field tracker :第二个是绑定函数以发布保存信号 + django 模型 utils 字段跟踪器:
@receiver(post_save, sender=Delegate)
def create_change_booking(sender,instance, signal, created, **kwargs):
if created:
previous_excursion = get it from django model utils field tracker
#change booking
And another solution is in pre_save as you are running:另一个解决方案是在您运行时在pre_save中:
@receiver(pre_save, sender=Delegate)
def my_callback(sender, instance, *args, **kwargs):
previous_excursion = Delegate.objects.get(self.pk).excursion
if instance.pk and instance.excursion != previous_excursion:
#change booking
You can use django model utils to track django model fields.您可以使用 django 模型工具来跟踪 django 模型字段。 check this example.
检查这个例子。
pip install django-model-utils
Then you can define your model and use fieldtracker in your model .然后你可以定义你的模型并在你的模型中使用 fieldtracker 。
from django.db import models
from model_utils import FieldTracker
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
tracker = FieldTracker()
status = models.CharField(choices=STATUS, default=STATUS.draft, max_length=20)
after that in post save you can use like this :之后在后期保存你可以这样使用:
@receiver(post_save, sender=Post)
def my_callback(sender, instance,*args, **kwargs):
print (instance.title)
print (instance.tracker.previous('title'))
print (instance.status)
print (instance.tracker.previous('status'))
This will help you a lot to do activity on status change.这将帮助你做很多关于状态变化的活动。 as because overwrite save method is not good idea.
因为覆盖保存方法不是一个好主意。
As an alternative and if you are using Django forms:作为替代方案,如果您使用的是 Django 表单:
The to-be version of your instance is stored in form.instance
of the Django form of your model.您的实例的未来版本存储在
form.instance
的 Django 形式的form.instance
中。 On save, validations are run and this new version is applied to the model and then the model is saved.保存时,将运行验证并将此新版本应用于模型,然后保存模型。
Meaning that you can check differences between the new and the old version by comparing form.instance
to the current model.这意味着您可以通过将
form.instance
与当前模型进行比较来检查新旧版本之间的差异。
This is what happens when the Django Admin's save_model
method is called.这就是调用 Django Admin 的
save_model
方法时发生的情况。 (See contrib/admin/options.py) (参见 contrib/admin/options.py)
If you can make use of Django forms, this is the most Djangothic way to go, I'd say.如果您可以使用 Django 表单,我会说这是最 Djangothic 的方式。
This is the essence on using the Django form for handling data changes:这是使用 Django 表单处理数据更改的本质:
form = ModelForm(request.POST, request.FILES, instance=obj)
new_object = form.instance # not saved yet
# changes are stored in form.changed_data
new_saved_object = form.save()
form.changed_data
will contain the changed fields which means that it is empty if there are no changes. form.changed_data
将包含已更改的字段,这意味着如果没有更改,它是空的。
There's yet another option:还有另一种选择:
Django's documentation has an example showing exactly how you could do this by overriding model methods. Django 的文档有一个示例,显示了如何通过覆盖 model 方法来做到这一点。
In short:简而言之:
Model.from_db()
to add a dynamic attribute containing the original valuesModel.from_db()
以添加包含原始值的动态属性Model.save()
method to compare the new values against the originalsModel.save()
方法以将新值与原始值进行比较This has the advantage that it does not require an additional database query.这样做的好处是不需要额外的数据库查询。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.