Django 获取所有 objects 的多对多字段包含过滤器

Django get all objects whose many to many filed contains a filter

我有 3 个模型:

现在,给定一个城市 object 和一个头衔 object,我想查询所有在其实例中具有这些 object 的人。基本上类似于“纽约的所有律师”。

class City(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name=models.CharField(max_length=40)
    state=models.CharField(max_length=15)

class Title(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title_name=models.CharField(max_length=40)

class Contact(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name_surname = models.CharField(max_length=60)
    title = models.ManyToManyField(Title)
    city = models.ManyToManyField(City)

您可以过滤:

Contract.objects.filter(
    <strong>title__title_name</strong>='Lawyer',
    <strong>city__name</strong>='NY'
)

但是,建模意义不大,因为这里一个Contract涉及多个Title和多个City , 但不清楚哪个标题属于哪个城市。

假设我们有一个人在纽约是软件工程师,在洛杉矶是酒保,那么建模无法区分这个人和纽约的酒保,和洛杉矶的一名软件工程师。

我们可以用 PersonContract 来表示城市和标题,因此:

class City(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name=models.CharField(max_length=40)
    state=models.CharField(max_length=15)

class Title(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title_name=models.CharField(max_length=40)

class <strong>Person</strong>(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=Falsee)
    name_surname = models.CharField(max_length=60)

class Contact(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    person = models.<strong>ForeignKey(</strong>Person, on_delete=models.CASCADE<strong>)</strong>
    title = models.<strong>ForeignKey(</strong>Title, on_delete=models.CASCADE<strong>)</strong>
    city = models.<strong>ForeignKey(</strong>City, on_delete=models.CASCADE<strong>)</strong>

那么我们可以确定这样的人:

Person.objects.filter(
    <strong>contract__title__title_name='Lawyer'</strong>,
    <strong>contract__city__name='NY'</strong>
)

然后我们检索所有 Person 至少有 Contract 的律师作为 title_name,纽约作为 name 作为 city .