#8046 closed (fixed)
filter() on a related multi-valued manager joins to too many tables.
Reported by: | Malcolm Tredinnick | Owned by: | Malcolm Tredinnick |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
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.
Change History (6)
comment:1 by , 16 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 16 years ago
comment:3 by , 16 years ago
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:4 by , 16 years ago
Two mailing list threads with some helpful test cases:
http://groups.google.com/group/django-users/browse_thread/thread/fc86ba8438468d35
http://groups.google.com/group/django-users/browse_thread/thread/274c5c57c08ed27c
comment:5 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | new → 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.
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 toall()
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.