Opened 3 years ago

Closed 3 years ago

#17821 closed Bug (invalid)

Extra fields on many-to-many relationships

Reported by: jedlau@… Owned by: nobody
Component: Documentation Version: master
Severity: Normal Keywords: many-to-many intermediate model
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

Existing text

As you are using an intermediate model, you can also query on its attributes:

# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
...     group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]

Bug Description
I'm surprised that this query worked, since Person doesn't have a group attribute. I think the group attribute is supposed to be reached through the intermediate model, membership:

# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
...     membership__group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]

Change History (1)

comment:1 Changed 3 years ago by aaugustin

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to invalid
  • Status changed from new to closed

This works as designed, but you have to look at it the other way round :)

Start with a regular many-to-many between Person and Group. You can write Person.objects.filter(group='xxx'). Technically, the database does two JOINS (because of the intermediate table) but that doesn't appear in the Python API -- I can't imagine something that would make sense in Person.objects.filter(???_group='xxx').

Now, you want to save some attributes on the relation, and you add an intermediate model. You still expect Person.objects.filter(group='xxx') to work like it used to! However, if you want to query the attributes of the intermediate model, Django needs a way to identify it, hence the membership__ prefix.

In other words: with an intermediate model, you have two possible prefixes:

  • membership__ => queries the intermediate model
  • group__ => queries the target model

I hopes this helps!

Note: See TracTickets for help on using tickets.
Back to Top