post_save 信号和关系

sog*_*ing 5 python django signals django-models django-admin

我正在应用 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')
Run Code Online (Sandbox Code Playgroud)

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

更新:在当前代码下方,尚未按预期工作。我已经通过 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):
    # [...]
Run Code Online (Sandbox Code Playgroud)

解决方案

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

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

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

  1. 项目.save()
  2. PersonProjectMembership.save()

所以很正常,在 Project.post_save 上的员工仍然是空的。我必须做的是聆听 PersonProjectMembership post_save 信号:

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

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

sog*_*ing 2

在对我的代码进行了大量研究并进行了简单的测试之后,我按照 krasnoperov 的建议尝试了 m2m_changed 信号。我意识到,如果您明确声明一个“通过”模型,在我的例子中是“PersonProjectMembership”,那么这个信号就不能很好地工作。

然后我又想了想,将我的方法链接到“PersonProjectMembership”的 post_save 信号。效果很好。