Innovate anywhere, anytime withruncode.io Your cloud-based dev studio.
Django

Querying with Django Q Objects

2022-07-25

Django Q objects:

Q object encapsulates a SQL expression in a Python object that can be used in database-related operations. Using Q objects we can make complex queries with less and simple code.

For example, this Q object filters whether the question starts wiht 'what':

from django.db.models import Q
Q(question__startswith='What')

Q objects are helpfull for complex queries because they can be combined using logical operators and(&), or(|), negation(~)

For example, this statement returns if the question starts with 'who' or with 'what'.

Q(question__startswith='Who') | Q(question__startswith='What')

Note:>If the operator is not included then by default 'AND' operator is used

The following code is source of Q class:

class Q(tree.Node):
  AND = 'AND'
  OR = 'OR'
  default = AND

  def __init__(self, *args, **kwargs):
    super(Q, self).__init__(children=list(args) + list(six.iteritems(kwargs)))


  def _combine(self, other, conn):
    if not isinstance(other, Q):
      raise TypeError(other)
    obj = type(self)()
    obj.connector = conn
    obj.add(self, conn)
    obj.add(other, conn)
    return obj

  def __or__(self, other):
    return self._combine(other, self.OR)


 def __and__(self, other):
    return self._combine(other, self.AND)

  def __invert__(self):
    obj = type(self)()
    obj.add(self, self.AND)
    obj.negate()
    return obj

As you can interpret from above code, we have three operators 'or', 'and' and invert(negation) and the default operator is AND.

Dynamic querying with Q objects:

This is an interesting feature as we can use the operator module to create dynamic queries.

import operator
from django.db.models import Q
from your_app.models import your_model_object

q_list = [Q(question__startswith='Who'), Q(question__startswith='What')]
your_model_object.objects.filter(reduce(operator.or_, q_list))

We are performing the or operation using operator.or_

To use and operations simply execute:

your_model_object.objects.filter(reduce(operator.and_, q_list))

Q objects not only simplify complex queries, they are very handy for dynamic filtering.

To Know more about our Django CRM(Customer Relationship Management) Open Source Package. Check Code