8

Anyone know why this query_set doesn't return any values for me? Using filter separately, it works perfectly, so it seems .filter().filter() together is the wrong approach to filter for 'either or'.

ticket_query = request.event.tickets.filter(status='on-sale').filter(status='paused').prefetch_related('ticket_tax')
iacob
  • 20,084
  • 6
  • 92
  • 119
  • Possible duplicate of [Django Filters - or?](https://stackoverflow.com/questions/739776/django-filters-or) – trixn Jul 01 '18 at 08:50

3 Answers3

21

filter() with multiple parameters joins them with AND statements: https://docs.djangoproject.com/en/2.0/ref/models/querysets/#filter

To perform OR queries in django you can use Q objects:

from django.db.models import Q

ticket_query = request.event.tickets.filter(Q(status='on-sale') | Q(status='paused')).prefetch_related('ticket_tax')

More details here: https://docs.djangoproject.com/en/2.0/topics/db/queries/#complex-lookups-with-q

phil
  • 528
  • 3
  • 6
5

request.event.tickets.filter(status='on-sale') returns all objects with status='on-sale', and you are looking for objects with status='paused' in that list, which is why you are getting an empty queryset.

Chaining 2 filters is fine if it is a ManyToManyField where you can have multiple objects for the same field OR if you are chaining for 2 separate fields eg. request.event.tickets.filter(status='on-sale').filter(is_available=True), which returns all tickets that are on sale and are available.

The simplest approach for this problem would be to use __in in the filter like this: ticket_query = request.event.tickets.filter(status__in=['on-sale', 'paused']).prefetch_related('ticket_tax').

Hope this helps. :)

Ruhi123
  • 99
  • 6
4

Chaining filter like you have done applies the subsequent filter to the queryset returned by the previous filter, i.e. it acts like an AND condition, not OR.

You can use the | operator to combine two queries:

ticket_query = request.event.tickets.filter(status='on-sale') | request.event.tickets.filter(status='paused')
iacob
  • 20,084
  • 6
  • 92
  • 119