modlinltd/django-advanced-filters

Feature request: Allow AND operator to work with M2M relationship

fcorallini opened this issue · 5 comments

class Article(models.Model):
    ...
    tags = models.ManyToManyField('Tag', blank=True, verbose_name=_(u"Tags ..."))

With a simple model like this, I can't filter Articles with tag "Cars" AND "Lamborghini"

class Article(models.Model):
    ...
    tags = models.ManyToManyField('Tag', blank=True, verbose_name=_(u"Tags ..."))

With a simple model like this, I can't filter Articles with tag "Cars" AND "Lamborghini"

I am also getting the same issue with M2M fieds

Could either of you contribute a failing test case to our test project & test cases? It will make fixing it much easier 🙏

I'm working on building out a test case in your test suite for this issue but the gist of it that I can see is that when you use contains for an M2M relationship the AND clause doesn't get calculated properly.

example from my test system:

AdvancedFilter object (1) (AND: ['attributes__name__icontains', 'bar'], ['attributes__name__icontains', 'foo'])
this doesn't return the results that have attributes foo and bar, it returns nothing.

UPDATE: I see what the issue is, this is creating a Q object that is looking for a single relation where the name is foo and bar at the same time, that is why this doesn't work. In order to handle this scenario the way I found to do it is that it needs chained filters for each condition:

User.objects.filter(
Q(attributes__name__contains="foo")
).filter(Q(attributes__name__contains="bar"))

this ensures both attributes exist individually.

Here is an example of the issue:
https://stackoverflow.com/questions/55400746/django-q-queries-on-the-same-field

Sorry just got back to this. Let me know if this PR covers what you want #174

Thank you for submitting the test @curtisstpierre, it clarifies what is requested, so I've now labelled the issue as an "enhancement".

We could add validation to prevent many-to-many fields to be accidentally used in this way while not fully implemented.

To fully support M2M field operations like the ones described above, we'd need to:

  1. Design a UI that will support M2M field, and clearly indicate to users. Perhaps a multi-option select field can work.
  2. Implement a schema for storing these "chained queries" in the AdvancedFilter.b64_query field.
  3. Add a few more cases, e.g. ensure we avoid duplicates (as described here).

I don't think I'll have time to work on this any time soon. That said, contributions are more than welcome