Search code examples
djangodjango-viewsdjango-querysetdjango-q

django : using Q objects


I have these 2 queries :

gifts = Products.objects \
    .filter(entry_query,in_stock__icontains='A-in') \
    .filter(~Q(title__icontains='Not Found'))

and

gifts1 = Products.objects \
    .filter(('city__name__iregex', 'Delhi'),in_stock__icontains='A-in') \
    .filter(~Q(title__icontains='Not Found'))

If I do gifts = gifts | gifts1 I get the following error:

error user-defined function raised exception

If i use Q objects like this:

gifts = Products.objects \
    .filter((Q(entry_query) & Q(in_stock__icontains='A-in')) | Q(('city__name__iregex', 'Delhi'),in_stock__icontains='A-in') ) \
    .filter(~Q(title__icontains = 'Not Found'))

I again get the same error

Here entry query is

(OR: ('title__iregex', u'bag'), ('description__iregex', u'bag'),('source_website_url__iregex', u'bag'))

Can someone please tell me where am I going wrong


Solution

  • The error in the first approach is because gifts1 and gifts are already QuerySets (try typeof(gifts)), so you cannot use | between them. It is like if you were using 'hi'|'goodbye'. You only use | for Q objects.

    What you did the second time was almost correct, except the syntax: use | for OR and & for AND. The comma does not provide any logical operation on the Q, leading to a different argument on the filter, leading to an error.

    Notice that both using & and joining filters are equivalent in Django (or are supposed to be), but your first approach of getting gift and gift1 as different QuerySets and evaluating them is different: that approach leads to two accesses (hits) to the database, while joining filters or Q objects in a single filter only hits it once.

    As a rule of thumb, you should minimize the number of hits to the db.

    Hope this helps