我需要检测一个post_remove信号,所以我写了:
def handler1(sender, instance, action, reverse, model, pk_set, **kwargs):
if (action == 'post_remove'):
test1() # not declared but make a bug if it works, to detect :)
m2m_changed.connect(handler1, sender=Course.subscribed.through)
如果我用'post_add'改变'post_remove'就可以了..这是关于post_remove的django的错误吗?
我使用该模型,并在“订阅”的两个值之间切换(所以添加了一个,删除了一个)
class Course(models.Model):
name = models.CharField(max_length=30)
subscribed = models.ManyToManyField(User, related_name='course_list', blank=True, null=True, limit_choices_to={'userprofile__status': 'student'})
我看过一篇有django错误的帖子,也许它还没有被修复......(或者它是我^^)
答案 0 :(得分:6)
据我所知,这不是一个错误,只是Django没有以你期望的方式更新m2m关系。它不会删除要删除的关系,然后添加新的关系。相反,它清除所有m2m关系,然后再添加它们。
有一个相关问题Django signal m2m_changed not triggered,它链接到故障单13087。
因此,您可以使用pre_clear
信号检查post_clear
或m2m_changed
操作,但由于这些操作未提供pk_set
,因此无法找到保存前的相关条目,如您在your other question中所做的那样。
答案 1 :(得分:6)
感谢Alasdairs comment我找到了解决方案并将其发布在此处 - 也许有人可以使用它。
<强> models.py 强>
class Team(models.Model):
name = models.CharField(max_length=100)
members = models.ManyToManyField(User)
pre_save.connect(team_pre_save, sender=Team)
m2m_changed.connect(team_members_changed, sender=Team.members.through)
<强> signals.py 强>
def team_pre_save(sender, instance, **kwargs):
if instance.pk:
instance._old_m2m = set(list(instance.members.values_list('pk', flat=True)))
else:
instance._old_m2m = set(list())
def team_members_changed(sender, instance, **kwargs):
if kwargs['action'] == "post_clear":
# remove all users from group
group = Group.objects.get(name='some group')
for member in instance._old_m2m:
user = User.objects.get(pk=member)
user.groups.remove(group)
if kwargs['action'] == "post_add":
added_members = list(kwargs['pk_set'].difference(instance._old_m2m))
deleted_members = list(instance._old_m2m.difference(kwargs['pk_set']))
if added_members or deleted_members:
# we got a change - do something, for example add them to a group?
group = Group.objects.get(name='some group')
for member in added_members:
user = User.objects.get(pk=member)
user.groups.add(group)
for member in deleted_members:
user = User.objects.get(pk=member)
user.groups.remove(group)
答案 2 :(得分:1)
所以现在我可以根据我的m2m
自动设置ativo True或Falseclass Servico(BaseMixin):
descricao = models.CharField(max_length=50)
#This inheritance from User of django that has is_active boolean field
class UsuarioRM(Usuario):
servicos = models.ManyToManyField(Servico,related_name='servicos_usuario', blank=True)
# SIGNALS
from django.db.models import signals
from django.db.models.signals import m2m_changed
def usuariorm_servicos_changed(sender, **kwargs):
action = kwargs.pop('action', None)
pk_set = kwargs.pop('pk_set', None)
instance = kwargs.pop('instance', None)
if action == "pre_clear":
if instance.servicos.all():
servicos = instance.servicos.all()
for servico in servicos:
instance.servicos.remove(servico)
instance.save()
else:
instance.is_active = False
instance.save()
if action == "post_add":
if pk_set:
instance.is_active = True
else:
instance.is_active = False
instance.save()
m2m_changed.connect( usuariorm_servicos_changed, sender=UsuarioRM.servicos.through )