django admin中的用户组分配轨道

时间:2016-02-10 09:36:11

标签: python django

在Django中,我想跟踪如何将组分配给用户,现在我们通过Django Admin为用户分配组。我尝试在User.groups.through表上使用m2m_changed信号,但在分配给User的组中,在Django admin中,它首先清除现有的用户组并添加更新的组,以便创建不必要的调用" pre_clear"和" post_clear"信号的作用,因此信号在所有情况下都不起作用。

任何人都可以建议我覆盖Django用户保存方法并在该方法中处理更改的组吗?或任何其他方式来跟踪用户组分配?

我正在使用Django 1.6

1 个答案:

答案 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_clearpost_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()