1

I have an article model with m2m relationships to model Tag,

I intend to filter articles which have tags both "python" and "django"

I tried Q along with &

In [184]: from django.db.models import Q

In [185]: articles = Article.objects.filter(Q(tags__name="python") & Q(tags__name=
   ...: "django"))

In [186]: articles
Out[186]: <QuerySet []>

It return a null Queryset

Alternatively I tested

In [202]: articles = Article.objects.filter(Q(tags__name="python")).filter(Q(tags_
   ...: _name="django"))

In [203]: articles
Out[203]: <QuerySet [<Article: Test new tags>, <Article: Django Tutorial>]>

I worked and solved the problem.

However, I am very confused with the failing of Q()&Q(), should I alway utilize filter chain rather than Q() combination to avoid mistakes?

AbstProcDo
  • 19,953
  • 19
  • 81
  • 138
  • 1
    None of these will work, since Django assumes that you are talking about the *same* related tag, and a tag can not have as name `"python"` and `"django"` at the same time. – Willem Van Onsem Jul 26 '18 at 21:57

2 Answers2

1

By doing .filter(Q(tags__name="python") & Q(tags__name="django"), you're asking filter to look for Articles with a related Tag that satisfies both name="python" and name="django" at the same time, which naturally can't be true.

By doing two separate .filter()s, the related Tags that satisfy the two conditions don't have to be the same one, since they are done on two separate querysets, so they will be able to find Articles that have a Tag whose name is 'python', and another Tag whose name is 'django'.

blhsing
  • 91,368
  • 6
  • 71
  • 106
0

Use | operator (Logical OR operator) instead of & operator (Logical AND operator).
Try this,

from django.db.models import Q

Article.objects.filter(Q(tags__name="python") | Q(tags__name="django"))
                                            ^^^^^

See this So post also, Django Filters -OR

JPG
  • 82,442
  • 19
  • 127
  • 206