【问题标题】:Is it possible to selectively suppress a post_save (or other) signal in Django?是否可以在 Django 中选择性地抑制 post_save (或其他)信号?
【发布时间】:2011-06-16 14:39:48
【问题描述】:

我想知道是否可以在创建对象时选择性地抑制 Django 信号(例如 post_savepost_init),或者,向其发送某些参数。

我拥有的是一个User 对象,它可以在我的代码中以多种不同的方式和位置创建。所以要自动为每个User 分配一个自定义Profile 对象,我使用post_save 信号。但是,在一种特定情况下,我想将额外信息绑定到创建的Profile 对象。将它作为参数传递给post_save 信号会很棒,但看起来不太可能。

另一种选择是手动创建Profile 对象,但我需要在保存User 之后创建,否则Profile 无法绑定到User 实例。但是,保存 User 实例会导致通过信号调用的函数创建另一个 Profile

我不能只获取刚刚创建的Profile 对象,因为这会导致'Profile' object is unsubscriptable 错误。有什么建议吗?

更新:

以下是可能情况的示例:

def createUserProfile(sender, instance, created, **kwargs):
if created:  
    profile, created = Profile.objects.get_or_create(user=instance)
    if extra_param:
        profile.extra_param = extra_param
    profile.save()

post_save.connect(createUserProfile, sender=User)

def signup(request):
   ...
   extra_param = 'param'
   user.save()

如何将signup 方法中的变量extra_param 获取到createUserProfile 方法,并将其作为Profile 对象的一部分存储在其中?

【问题讨论】:

    标签: django django-signals


    【解决方案1】:

    为什么这对你不起作用?

    user = User(...)
    user.save()
    # profile has been created transparently by post_save event
    profile = user.profile
    profile.extra_stuff = '...'
    profile.save()
    

    如果你沉迷于传递给事件的参数,可能但很邪恶:

    user = User()
    user._evil_extra_args = { ... }
    user.save()
    
    In event:
    extra_args = getattr(user, '_evil_extra_args', False)
    

    这是邪恶的,因为阅读您的代码的人将不知道那些 _evil_extra_args 到底是为了什么以及它是如何工作的。

    【讨论】:

    • 我最后选择了 evil 选项,因为第一个选项给出了某种并发错误(当我尝试访问配置文件时,db 对象仍然被 save() 事件锁定)。
    【解决方案2】:

    延迟post_save 是不可能的(除非你想entirely disconnect it),但也没有必要。将参数传递给配置文件根本不是问题:

    class UserProfile(models.Model):  
        user = models.ForeignKey(User)
        other = models.SomeField()
    
    def create_user_profile(sender, instance, created, other_param=None, **kwargs):  
        if created:  
           profile, created = UserProfile.objects.get_or_create(user=instance)
           profile.other(other_param) # or whatever
           profile.save()
    
    post_save.connect(create_user_profile, sender=User, other_param=p)
    

    【讨论】:

    • 如果我只想在一种情况下发送该参数,并且 post_save.connect 定义在创建 User 对象本身的函数之外的某个地方,该怎么办?这将如何运作?
    • 我认为我们中的一个人误解了另一个人,所以我在我的问题中添加了一个示例,希望能澄清问题。
    猜你喜欢
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    • 2012-08-07
    • 2014-05-23
    • 2017-10-10
    • 2021-11-06
    • 2016-05-04
    • 2011-09-21
    相关资源
    最近更新 更多