1

My question concerns the many-to-many section of the django models docs:

It is mentioned there that by using an intermediary model it is possible to query on the intermediary model's attributes like so:

Person.objects.filter(
    group__name='The Beatles',
    membership__date_joined__gt=date(1961,1,1))

However for the other many-to-many model (Group) a similar query results in a FieldError:

# which groups have a person name containing 'Paul'?
Group.objects.filter(person__name__contains="Paul")

Yet queries that reference the junction table explicity do work:

Person.objects.filter(membership__group__name__contains="The Beatles")
Group.objects.filter(membership__person__name__contains="Paul")

Shouldn't Group therefore have access to Person via the junction model?

Models:

from django.db import models

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

    def __str__(self):
        return self.name

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

    def __str__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)
upgrd
  • 720
  • 7
  • 16
  • Can you add your Models – JSRB Nov 12 '22 at 08:22
  • The models are in the docs section I linked, but yes, will do. – upgrd Nov 12 '22 at 08:24
  • Have you read [this thread](https://stackoverflow.com/questions/37650362/understanding-manytomany-fields-in-django-with-a-through-model)? It describes the point of using `through` in a `ManyToManyField` and indeed it's probably not what you expect! – scūriolus Nov 12 '22 at 09:07
  • @scūriolus thanks! but how exactly does this provide an answer to my question? Imo the thread just explains that many-to-many relationships are implemented with junction tables anyway, but one can also explicate a junction table with an intermediary model. However I think this does not explain my question regarding querying through an intermediary model. – upgrd Nov 12 '22 at 09:36

1 Answers1

0

"The model that defines the ManyToManyField uses the attribute name of that field itself, whereas the “reverse” model uses the lowercased model name of the original model, plus '_set' (just like reverse one-to-many relationships)." (docs: Many-to-many relationships)

So instead of

Group.objects.filter(person__name__contains="Paul")

the correct query is

Group.objects.filter(members__name__contains="Paul")

since the related model is accessible via the name of the field attribute (not the model).

upgrd
  • 720
  • 7
  • 16