在Django中,如何在Group添加或删除用户时获取信号?

时间:2011-10-26 05:55:04

标签: django django-models django-admin

在Django管理员中,我有时会向(现有)组添加或删除用户。当发生这种情况时,我希望能够运行一个功能。

我只是使用标准的用户和群组模型。

我已经通过m2m_changed来查看信号,但它似乎需要一个通过类 - 我不认为在这种情况下有一个。

4 个答案:

答案 0 :(得分:6)

来自django doc

  

sender - 描述ManyToManyField的中间模型类。定义多对多字段时,将自动创建此类;您可以使用多对多字段中的through属性访问它。

订阅m2m_changed时如此:

@receiver(m2m_changed)
def my_receiver(**kwargs):
    from pprint import pprint
    pprint(kwargs)

你会收到一堆像这样的信号(缩短):

{'sender': <class 'django.contrib.auth.models.User_groups'>,
 'action': 'post_add',
 'instance': <User: bouke>,
 'model': <class 'django.contrib.auth.models.Group'>,
 'pk_set': set([1]),
 'reverse': False,
 'signal': <django.dispatch.dispatcher.Signal object at 0x101840210>,
 'using': 'default'}

因此,用户bouke已添加到pk_set组:[1]。但是我注意到管理员布局会清除所有组,然后重新添加所选组。您将收到的信号是pre_clearpost_clearpre_addpost_add。使用这些信号的组合,您可以存储前后组。对这些列表进行差异处理,您可以为用户添加已删除和添加的组。

请注意,在编辑组而不是用户时,信号是相反的(pk_setinstance)。

答案 1 :(得分:1)

您需要使用m2m_changed作为接收器创建信号。根据{{​​3}}:

  

在模型实例上更改ManyToManyField时发送信号。严格来说,这不是模型信号,因为它是由ManyToManyField发送的。

所以,最简单的实现如下:

@receiver(m2m_changed)
def signal_handler(**kwargs):
    from pprint import pprint
    pprint(kwargs)

在您的情况下,您希望在群组中添加或删除用户时执行某些操作,因此您可以在action 'pre_add'时使用'post_add'参数},'pre_remove''post_remove'。您还可以利用pk_set参数,该参数包含已添加到关系中或从关系中删除的主键值。

@receiver(m2m_changed)
def signal_handler_when_user_is_added_or_removed_from_group(action, instance, pk_set, model, **kwargs):
    if model == Group:
        if action == 'pre_add':
            # TODO: add logic
            pass
        elif action == 'post_add':
            # TODO: add logic
            pass
        # handle as many actions as one needs
    # The following for loop prints every group that were
    # added/removed.
    for pk in pk_set:
        group = Group.objects.get(id=pk)
        print(group)

答案 2 :(得分:0)

您会在Django documentation(v1.11)中看到,所需的发件人应该是属于through字段的中间ManyToMany字段,无论定义了什么。如果您将其注册为发件人,那么您将收听例如“用户向自己添加组”以及“用户向自己添加组”的邮件。

self.walrus.groups.remove(self.peon_group)

@receiver(signal=m2m_changed, sender=User.groups.through)
def adjust_group_notifications(instance, action, reverse, model, pk_set, using, *args, **kwargs):
    if model == Group and not reverse:
        logger.info("User %s is modifying their relation to groups «%s»", instance.username, pk_set)
        …
        # Walrus example fits here
    else:
        logger.info("Group %s is modifying its relation to users «%s»", instance, pk_set)
        …
    return

答案 3 :(得分:-1)

尝试使用django-celery实现此目标可能会更好,这样您就可以编写自定义任务,并且可以根据特定条件(例如删除或添加)来触发某项任务。