简体   繁体   English

什么时候在django中使用pre_save,save,post_save?

[英]when to use pre_save, save, post_save in django?

I see I can override or define pre_save, save, post_save to do what I want when a model instance gets saved. 我看到我可以覆盖或定义pre_save, save, post_save以在保存模型实例时执行我想要的操作。

Which one is preferred in which situation and why? 在哪种情况下哪一个首选?为什么?

I shall try my best to explain it with an example: 我将尽力用一个例子来解释它:

pre_save and post_save are signals that are sent by the model. pre_savepost_save是模型发送的信号 In simpler words, actions to take before or after the model's save is called. 简单来说,调用模型save之前或之后的操作。

A save triggers the following steps save 会触发以下步骤

  • Emit a pre-save signal. 发出预保存信号。
  • Pre-process the data. 预处理数据。
  • Most fields do no pre-processing — the field data is kept as-is. 大多数字段不进行预处理 - 字段数据保持原样。
  • Prepare the data for the database. 准备数据库的数据。
  • Insert the data into the database. 将数据插入数据库。
  • Emit a post-save signal. 发出保存后信号。

Django does provide a way to override these signals. Django确实提供了一种覆盖这些信号的方法。

Now, 现在,

pre_save signal can be overridden for some processing before the actual save into the database happens - Example: (I dont know a good example of where pre_save would be ideal at the top of my head) 在实际保存到数据库之前,可以覆盖pre_save信号进行某些处理 - 例如:(我不知道pre_save在我脑海中最理想的地方的一个很好的例子)

Lets say you have a ModelA which stores reference to all the objects of ModelB which have not been edited yet. 比方说你有一个ModelA存储参考的所有对象ModelB没有被编辑过呢。 For this, you can register a pre_save signal to notify ModelA right before ModelB 's save method gets called (Nothing stops you from registering a post_save signal here too). 为此,您可以注册一个pre_save信号,以便在ModelBsave方法之前通知ModelA (此处也没有阻止您注册post_save信号)。

Now, save method (it is not a signal) of the model is called - By default, every model has a save method, but you can override it: 现在,调用模型的save方法(它不是信号) - 默认情况下,每个模型都有一个save方法,但是你可以覆盖它:

class ModelB(models.Model):
    def save(self):
        #do some custom processing here: Example: convert Image resolution to a normalized value
        super(ModelB, self).save()

Then, you can register the post_save signal (This is more used that pre_save ) 然后,你可以注册post_save信号(这更多用于pre_save

A common usecase is UserProfile object creation when User object is created in the system. 一个常见的用例是在系统中创建User对象时创建UserProfile对象。

You can register a post_save signal which creates a UserProfile object that corresponds to every User in the system. 您可以注册post_save信号,该信号创建与系统中每个User对应的UserProfile对象。

Signals are a way to keep things modular, and explicit. 信号是保持模块化和显式化的一种方式。 (Explicitly notify ModelA if i save or change something in ModelB ) (明确通知ModelA如果我save或改变的东西ModelB

I shall think of more concrete realworld examples in an attempt to answer this question better. 为了更好地回答这个问题,我会想到更具体的现实世界的例子。 In the meanwhile, I hope this helps you 同时,我希望这会对你有所帮助

pre_save

it's used before the transaction saves. 它在事务保存之前使用。

post_save

it's used after the transaction saves. 它在事务保存后使用。

You can use pre_save for example if you have a FileField or an ImageField and see if the file or the image really exists. 您可以使用pre_save如果你有一个例如FileFieldImageField ,看看fileimage确实存在。

You can use post_save when you have an UserProfile and you want to create a new one at the moment a new User it's created. 您可以在拥有UserProfile时使用post_save ,并且希望在创建新User时创建新的。

Don't forget about recursions risk. 不要忘记递归风险。 If you use post_save method with instance.save() calling, instead of .update method, you should disconnect your post_save signal: 如果你使用post_save方法调用instance.save()而不是.update方法,你应该断开你的post_save信号:

Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)[source] To disconnect a receiver from a signal, call Signal.disconnect(). Signal.disconnect(receiver = None,sender = None,dispatch_uid = None)[source]要断开接收器与信号的连接,请调用Signal.disconnect()。 The arguments are as described in Signal.connect(). 参数如Signal.connect()中所述。 The method returns True if a receiver was disconnected and False if not. 如果接收器断开连接,则该方法返回True,否则返回False。

The receiver argument indicates the registered receiver to disconnect. receiver参数表示已注册的接收器断开连接。 It may be None if dispatch_uid is used to identify the receiver. 如果dispatch_uid用于识别接收器,则它可以是None。

... and connect it again after. ...之后再次连接。

update() method don't send pre_ and post_ signals, keep it in mind. update()方法不发送pre_和post_信号,记住它。

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

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