Code

Opened 6 years ago

Closed 6 years ago

Last modified 3 years ago

#8046 closed (fixed)

filter() on a related multi-valued manager joins to too many tables.

Reported by: mtredinnick Owned by: mtredinnick
Component: Database layer (models, ORM) Version: master
Severity: Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

Because related managers are treated as filter() calls internally, filtering on a related attribute is the same as chained filter() calls, which leads to unintuitive behaviour on many-to-many relations and reverse ForeignKey relations.

Attachments (0)

Change History (6)

comment:1 Changed 6 years ago by mtredinnick

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 6 years ago by mtredinnick

This isn't the bug I thought it was (at least, I can't repeat the original situation where I though I saw something going wrong). There's still a problem, as indicated in this thread, there's still some likely incorrect behaviour with ManyToManyField(through=...).

Any subsequent filters are being treated as extra filters and joining separately to the intermediate table. The caller has no way to say it's the same filter (equivalent to filter(thingA, thingB)) (which is why this is a bug). We should, by default, be treating the first filter as a continuation of the related object filtering and if somebody ahs a case where they don't want that, an intermediate call to all() will force them apart. The "natural" behaviour will almost always be correct here, though.

I'll still fix it -- it's not too hard to do, from what I can see -- but I just spent two hours trying to work out the original case (and failing) and cursing myself for not including more info in the bug report. So I'm now fixing that with what I understand the problem to be now.

comment:3 Changed 6 years ago by uzi

And to summarize that post of mine: "There should be a clean way to query a M2M relationship and filter based on the intermediate table." Right now, the ManyToManyField(through=...) feature doesn't appear to work that way, and I'll argue that it's confusing and incorrect... and I'm glad you (seem to) agree with me, Malcolm.

By all means, let me know if there's anything you'd like me to help with or test.

comment:5 Changed 6 years ago by mtredinnick

  • Resolution set to fixed
  • Status changed from new to closed

(In [8472]) Fixed #8046 -- The first filter() call on a related manager for many-to-many
fields no longer creates duplicate copies of the join table(s). Basically, this
means filters on the join table (for ManyToManyField(through=...)) and complex
filters in the normal (non-through) case don't produce incorrect or duplicate
results.

comment:6 Changed 3 years ago by jacob

  • milestone 1.0 deleted

Milestone 1.0 deleted

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.