Ali Osman Yüce
Ali Osman Yüce

Reputation: 3

Django ORM Queryset class behave different with same filters

This is a simple question.

I want to 2 filters at once with Queryset class. Let me explain.

from django.db.models import Q
import datetime
from .models import Asset

query_set = Asset.objects.filter(category__name="car")

date_query = {'eav__date__gte': datetime.datetime(2018, 9, 2, 0, 0), 'eav__date__lte': datetime.datetime(2018, 9, 14, 0, 0)}

number_query = {'eav__price__gte': '60', 'eav__price__lte': '600'}

total_query = {'eav__date__gte': datetime.datetime(2018, 9, 2, 0, 0), 'eav__date__lte': datetime.datetime(2018, 9, 14, 0, 0),'eav__price__gte': '60', 'eav__price__lte': '600'}

query_set = query_set.filter(Q(**number_query))

query_set = query_set.filter(Q(**date_query))

in this case, query_set is not empty!


query_set = query_set.filter(Q(**total_query))

in this case, query_set is empty!


Might someone explain the difference between two query please? Thanks in advance.

Upvotes: 0

Views: 54

Answers (2)

vipul prajapati
vipul prajapati

Reputation: 293

Use Q object to build query set. Its easiest way to work with queries in Django IN your case

query_set = query_set.filter(Q(**number_query))
query_set = query_set.filter(Q(**date_query))

These are different querysets.

query_set = query_set.filter(Q(**total_query))

Here you are combining two queries without AND ,OR condition so it's empty. Here you want AND condition I think so use this like Q(first_name__startswith='R') & Q(last_name__startswith='D')

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599490

This is because you are filtering across a many-valued relationship. As the docs explain:

Django has a consistent way of processing filter() calls. Everything inside a single filter() call is applied simultaneously to filter out items matching all those requirements. Successive filter() calls further restrict the set of objects, but for multi-valued relations, they apply to any object linked to the primary model, not necessarily those objects that were selected by an earlier filter() call.

So, your first case selects all those Assets with an EAV which matches the date requirements and an EAV which matches the price requirements, but not necessarily the same EAV. Your second case selects only those Assets for which there is an EAV which matches both requirements at the same time.

Upvotes: 0

Related Questions