简体   繁体   English

保存时检查以前的 model 值

[英]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:简而言之:

  1. override Model.from_db() to add a dynamic attribute containing the original values覆盖Model.from_db()以添加包含原始值的动态属性
  2. override the Model.save() method to compare the new values against the originals覆盖Model.save()方法以将新值与原始值进行比较

This has the advantage that it does not require an additional database query.这样做的好处是不需要额外的数据库查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM