首页 > 解决方案 > Django 两种相同的信号类型

问题描述

我不明白一起执行的 2 个信号如何相互关联。例如考虑以下内容:

from django.db import models
from django.contrib.auth.models import User
from PIL import Image
from django.db.models.signals import post_save
from django.dispatch import receiver


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    image = models.ImageField(default='default.jpg', upload_to='profile_pics')

    def __str__(self):
        return f'{self.user.username} Profile'  

    # Overriding save method-image resizing
    def save(self, **kwargs):
        super().save(kwargs)

        img = Image.open(self.image.path)

        if img.height > 300 or img.width > 300:
            output_size = (300, 300)
            img.thumbnail(output_size)
            img.save(self.image.path)  # save() of parent class

#Signals when a user is registered his profile is automatically updated
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile(user=instance)  #could do Profile.objects.create(user=instance) instead to replace the 2 lines
        instance.profile.save() #reverse query

我理解以下内容:

create_profile: 是我的接收函数。当 .save() 方法发生时它会做一些事情,在我们的例子中将创建一个 Profile 实例并保存它。

发件人:是实际发出信号的模型。所以在我们的例子中,如果我们希望在用户模型上执行保存方法时发出信号,那么发送者就是用户。

post_save 是信号

关于我现在的问题。我已经看到上述功能分解为以下两个功能。

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile(user=instance)


@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
    instance.profile.save() #reverse query

我知道这是没有意义的,因为我可以做我所做的,但我不明白我的 save_profile 函数如何“记住”在 create_profile 上创建的 Profile 实例?

据我所知, save_profile 是一个单独的函数,它没有引用 create_profile 函数(例如 create_profile 或 save_profile 主体)。

我假设当保存用户实例时执行 create_profile 函数,它会生成一个配置文件对象,然后执行 save_profile 函数,并且对于相同的用户实例,保存配置文件对象,但我仍然不明白它是如何知道我指的是同一个该实例制作的配置文件。

标签: django

解决方案


为什么你不说它是 Corey 教程的例子?

Corey 教程,第 8 部分,如果我没记错的话,他不必创建两个单独的信号,因为一个就足够了..

对于您的问题:功能是:

@receiver(post_save, sender=User)
def create_profile_handler(sender, instance, created, **kwargs):
   #Run each time a new user is created, and attach to the user a profile !
   #    sender - The model class (User)
   #    instance - The actual instance being saved. (User)
   #    created - A boolean. 'True' if a new record was created.

   if created:
       Profile.objects.create(user=instance) 
       #'create' - initialize and save a profile and attach it to the User



# Now, lets save the profile each time the user object is been saved.
@receiver(post_save, sender=User)
def save_profile_handler(sender, instance, **kwargs):
   instance.profile.save() # User.profile.save() - saves the profile

我们从 Django Docs中知道,create() 方法中包含 save() 操作。

因此,不仅第二个信号是多余的(因为我们可以在第一个信号中执行它的操作),而且 - save 本身有点多余(因为 create 调用 save)。


推荐阅读