在Django中,我想跟踪如何将组分配给用户,现在我们通过Django Admin为用户分配组。我尝试在User.groups.through表上使用m2m_changed信号,但在分配给User的组中,在Django admin中,它首先清除现有的用户组并添加更新的组,以便创建不必要的调用" pre_clear"和" post_clear"信号的作用,因此信号在所有情况下都不起作用。
任何人都可以建议我覆盖Django用户保存方法并在该方法中处理更改的组吗?或任何其他方式来跟踪用户组分配?
我正在使用Django 1.6
答案 0 :(得分:6)
这是Django的一个已知问题,它仅在1.9中修复: https://docs.djangoproject.com/en/1.9/releases/1.9/#related-set-direct-assignment
直接分配用于执行的ORM中的相关对象 clear()后跟add()调用。这导致了不必要的大数据 更改并阻止使用m2m_changed信号跟踪个人 多对多关系的变化。
直接赋值现在依赖于相关的新set()方法 默认情况下,管理员只处理现有的变更 相关集和新分配的集。以前的行为 可以通过调用set()替换直接赋值来恢复 关键字参数clear = True。
ModelForm,因此ModelAdmin,内部依赖直接 为多对多关系分配,因此现在使用 新的行为。
如果您手动使用user.groups.add(foo)
或user.groups.remove(foo)
,那么您当前的信号接收器应该可以正常工作。但是django admin使用赋值,因此它会导致清除并设置django-admin的每次保存。要在不更新到django 1.9的情况下解决此问题,您必须同时处理pre_clear
和post_add
:将已清除pks
存储到preclear中的某个“特殊”属性,然后计算添加的内容或除去。
def pre_clear_handler(sender, *args, **kwargs):
# ...
instance._cleared_groups_pk_set = set([group.pk for group in instance.groups.all()]) # or `set(instance.groups.all().values_list('pk', flat=True))
tracker = SomeTrackingModel()
tracker.removed_group_ids = instance._cleared_groups_pk_set
tracker.save() # post_add may not be called if groups are fully cleared
instance._changes_tracker_helper = tracker
def post_add_handler(sender, *args, **kwargs):
# ...
prev_groups_pk_set = getattr(instance, '_cleared_groups_pk_set', None)
if prev_groups_pk_set is not None:
not_realy_added_pk_set = kwargs['pk_set']
removed_pks = prev_groups_pk_set - not_realy_added_pk_set
realy_added_pks = not_realy_added_pk_set - prev_groups_pk_set
else:
removed_pks = set()
realy_added_pks = kwargs['pk_set']
tracker = getattr(instance, '_changes_tracker_helper', SomeTrackingModel())
tracker.removed_group_ids = removed_pks
tracker.added_group_ids = realy_added_pks
tracker.save()