post_save信号和关系

时间:2013-06-17 13:54:37

标签: python django django-models django-admin signals

我正在应用post_save信号来为每个对象应用用户权限,然后相应地过滤查询集。

我的模型是这样的:

class Project(models.Model):
    # Relations with other entities.
    employees = models.ManyToManyField('staff.Person', through='project.PersonProjectMembership',
                                       related_name='projects')
    research_groups = models.ManyToManyField('group.Group', related_name='projects',
                                             through='project.ProjectGroupMembership')
    departments = models.ManyToManyField('department.Department', related_name='projects',
                                         through='project.ProjectDepartmentMembership')

问题是:当我捕捉到保存后信号时,虽然我输入了部门的值,但研究组和研究组也是如此。员工,他们似乎总是空虚的。有什么我错过的吗?

更新:在当前代码下方,该代码尚未按预期工作。我已经通过m2m_changed更改了post_save。

from django.db.models.signals import m2m_changed
from django.db import models
from django.dispatch.dispatcher import receiver

class Project(models.Model):
    employees = models.ManyToManyField('staff.Person', through='project.PersonProjectMembership',
    related_name='projects')

class PersonProjectMembership(models.Model):
    project = models.ForeignKey('project.Project', related_name="person_memberships")
    person = models.ForeignKey('staff.Person', related_name="project_memberships")
    lead = models.BooleanField(default=False)
    position = models.CharField(max_length=50)
    project_manager = models.BooleanField(
        default=False
    )

    class Meta:
        permissions = (
            ('view_personprojectmembership', _('View person project membership')),
        )

@receiver(m2m_changed, sender=Project.employees.through)
def _on_save_project_assign_privileges(sender, instance, action, reverse, model, pk_set, using, **kwargs):
    # [...]

在我的项目模型中,我明确将PersonProjectMembership定义为m2m关系员工的中间模型:

class Project(models.Model):
    # Relations with other entities.
    employees = models.ManyToManyField('staff.Person', through='project.PersonProjectMembership', related_name='projects')

我保存项目的时间表如下:

  1. Project.save()
  2. PersonProjectMembership.save()
  3. 因此,在Project.post_save员工仍然是空的时候是正常的。我要做的就是收听PersonProjectMembership post_save信号:

    @receiver(post_save, sender=PersonProjectMembership)
    def my_listener(**kwargs):
        # do stuff [...]
    

    查看https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.ManyToManyField.throughhttps://docs.djangoproject.com/en/1.9/topics/signals/

2 个答案:

答案 0 :(得分:1)

您可能知道,Many2Many关系是通过附加表存储的,其中包含来自关系两端的主键。因此,使用Many2Many关系保存模型实例是两个步骤:

  1. 首先,实例是保存:创建数据库中的新记录,实例接收它的主键。 post_save此时被解雇。

  2. 之后,保存关系:创建关系表中的记录。此时发出m2m-changed信号。

  3. 换句话说,当post_save被触发时,m2m关系尚未处理。

    您可以查看文档:{​​{3}}

答案 1 :(得分:1)

在对我的代码进行了大量挖掘并进行简单的测试之后,我尝试了krasnoperov建议的m2m_changed信号。我意识到如果你在我的情况下明确声明一个“通过”模型,“PersonProjectMembership”,这个信号不会很好。

然后我再次想到并将我的方法链接到“PersonProjectMembership”的post_save信号。这非常有效。