在Django管理员中,我有时会向(现有)组添加或删除用户。当发生这种情况时,我希望能够运行一个功能。
我只是使用标准的用户和群组模型。
我已经通过m2m_changed来查看信号,但它似乎需要一个通过类 - 我不认为在这种情况下有一个。
答案 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_clear
,post_clear
,pre_add
,post_add
。使用这些信号的组合,您可以存储前后组。对这些列表进行差异处理,您可以为用户添加已删除和添加的组。
请注意,在编辑组而不是用户时,信号是相反的(pk_set
和instance
)。
答案 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)