Django - 管理多对多关系

Django - manager on ManyToMany relationship

我有3个模型

class Person(models.Model):
  name = models.CharField(max_length=128)

class Company(models.Model):
  name = models.CharField(max_length=128)
  members = models.ManyToManyField (Person, through = 'Membership', related_name = 'companies')

class Membership(models.Model):
  person = models.ForeignKey(Person, on_delete=models.CASCADE)
  company = models.ForeignKey(Company, on_delete=models.CASCADE)
  is_admin = models.BooleanField()

然后我可以调用 person.companies.all() 来获取与此人关联的公司列表。

如何创建一个经理来拥有与人员关联的公司列表,但他的人员是管理员(is_admin = True)?

您可以过滤:

person.companies.filter(<strong>membership__is_admin=True</strong>)

这将过滤结点 table Membership,这样它将只检索 Membership 已将 is_admin 设置为 CompanyCompany =14=].

另一种选择是通过以下方式检索:

Company.objects.filter(<strong>membership__is_admin=True, members=person</strong>)

您可以通过以下方式将其附加到 Person 模型:

class Person(models.Model):
    name = models.CharField(max_length=128)

    <strong>@property</strong>
    def admin_companies(self):
        return self.companies.filter(<strong>membership__is_admin=True</strong>)

您可以创建如下管理器:

managers.py:

from django.db import models

class AdminCompaniesManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().companies.filter(membership__is_admin=True)

然后在你的Person模型中(请提醒objects经理):

class Person(models.Model):
    name = models.CharField(max_length=128)
    objects = models.Manager()
    administered_companies = AdminCompaniesManager()

现在您可以轻松调用以下内容(例如在您的视图中):

my_person.administered_companies.all()

PS:一个非常有效的选项(例如,如果您在视图中并且需要给定人员的公司 ID 列表)是直接查询成员资格模型,因此您可以优化查询用于从数据库检索数据,避免连接:

Membership.objects.filter(is_admin=True, person=person).values_list('company_id')