#27303: Selecting multiple admin list_filters across relations return results that don't match both filters -------------------------------+------------------------------------ Reporter: Yeago | Owner: nobody Type: Bug | Status: new Component: contrib.admin | Version: 1.10 Severity: Normal | Resolution: Keywords: filterspec | Triage Stage: Accepted Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------+------------------------------------
Comment (by Connor Osborn): I filed a ticket [https://code.djangoproject.com/ticket/27388], for this same issue because Dango Rest Framework depended on the api of chaining filters as an AND. As Josh Smeaton pointed out chained filters are logically OR'd statements. I think this is so counter to intuition that it is reasonable to break backwards compatibility in an upcoming release. I think the current api is likely to cause more pain in the future than the pain that would be caused by breaking existing code. If a function gets passed a queryset it cannot assume that it can call filter and gather the results, because of the nature of OR, it will include more than desired if another filter had been previously applied. Perhaps most importantly, applying multiple joins for the purpose of ORing can lead to exponentially slow queries, because successive joins can have multiplicative factors on the number of rows. This was the original reason I filed the ticket, the successive joins resulted in a search of 1million rows for a table with originally several thousand. > I think I understand the point you're trying to make Steve. Do the docs here represent the different behaviours you're trying to put across? https://docs.djangoproject.com/en/1.10/topics/db/queries/#spanning-multi- valued-relationships > > Those docs primarily refer to multi-value relationships which I'm not certain is the use case you're trying to resolve. But to summarise: > > `.filter(multi__value__lookup=1, multi__value__other=2)` is equivalent to `(MVL=1 AND MVO=2)` because the WHERE clause targets a single join. > > {{{ > SELECT * FROM model > JOIN multi ON model.multi_id = multi.id > JOIN value on multi.value_id = value.id > WHERE value.MVL=1 AND value.MVO = 2 > }}} > > Where `.filter(multi__value__lookup=1).filter(multi__value__other=2)` is logically equivalent to `(MVL=1 OR MVO=2)` because MVL and MVO have separate joins, so they can both match independently since it's a multivalue relationship. > > {{{ > SELECT * FROM model > JOIN multi ON model.multi_id = multi.id > JOIN value on multi.value_id = value.id > JOIN multi m2 ON model.multi_id = m2.id > JOIN value v2 on multi.value_id = v2.id > WHERE value.MVL=1 AND v2.MVO = 2 > }}} > > Does this correctly summarise the behaviour? -- Ticket URL: <https://code.djangoproject.com/ticket/27303#comment:26> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/065.dd9c38dee0e795865ffcf44eee5ff121%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.