# Django QuerySet Examples (with SQL code included)

<h4 id="section-intro">Intro</h4>

<p>
In this article, you will find the most commonly used Django QuerySet examples with SQL codes.
</p>

<p>A QuerySet describes a collection of objects/rows from your database. At some point, QuerySets are being "converted" to SQL queries. And one of the important facts about them is they are **lazy**. What does it mean? They can be constructed, filtered, sliced, and passed around without actually hitting the database. And only in the listed below cases, they are being evaluated:</p>

<ul>
<li>
**Iteration**: A QuerySet is iterable, and it executes a database query the first time we iterate over it.
</li>
<li>
**Pickling/Caching**: Evaulated if we pickle or cache a QuerySet.
</li>
<li>
**repr(), len(), list()**: A QuerySet is being evaluated when we call <code>repr()</code>, <code>len()</code>, <code>list()</code> on it.
</li>
<li>
**Slicing**: A QuerySet is being sliced **with the step parameter** will hit the database.
</li>
</ul>

<p>More about that you can find <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#when-querysets-are-evaluated" target="_blank" rel="noopener">here</a>.</p>

<h4 id="section-intro">Getting Started</h4>

<p>Note that all code examples below are written and tested with the **Django 3.0.1** and **PostgreSQL 12** versions. And most of them will work on lower on higher versions of Django and for other **relational** database engines without any issues. </p> 

<p>As a main model(table) for the examples, we chose Django's built-in <code>User</code> model. 
If you are unfamiliar with it or want to have deeper understanding of it, please check the official <a href="https://docs.djangoproject.com/en/3.0/ref/contrib/auth/#user-model" target="_blank" rel="noopener">docs</a>.
</p>

<p>
There are many different fields(columns) in the User model. But we are going to use only some of them. The table below partially represents the <code>User</code> model and the data examples that we can store there.
</p>

<div style="overflow-x: auto;">
    <table class="u-full-width">
          <thead>
            <tr>
              <th>id</th>
              <th>first_name</th>
              <th>last_name</th>
              <th>is_active</th>
              <th>date_joined</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th>1</th>
              <td>John</td>
              <td>Doe</td>
              <td>t</td>
              <td>2020-03-18 14:20:32.02425+00</td>
            </tr>
            <tr>
              <th>4</th>
              <td>Jone</td>
              <td>Doe</td>
              <td>f</td>
              <td>2020-02-18 14:20:32.02425+00</td>
            </tr>
          </tbody>
        </table>
</div>
<p>
Of course, this isn't the actual table for the User model, there are many other missing fields/columns, we just listed only ones that we are going to use.
</p>

<h4 id="section-table">Contents</h4>

<ul style="list-style: none;">
<li>How to get the SQL query from the QuerySet?</li>
<li>How to do AND operation?</li>
<li>How to do OR operation?</li>
<li>How to do a not equal filtering?</li>
<li>How to do IN filtering?</li>
<li>How to do IS NULL or IS NOT NULL queries?</li>
<li>How to do SQL “LIKE” equivalent queries?</li>
<li>How to do comparison(>, >=, <, <=) operations?</li>
<li>How to do BETWEEN operation?</li>
<li>How to LIMIT the number of results in queryset?</li>
<li>How to ORDER the results in queryset?</li>
<li>How to get a single object from queryset?</li>

</ul>

<h4 id="section-query">How to get the SQL query from the QuerySet? </h4>

<p>Sometimes, we need to get the raw SQL query that is being generated and executed behind the scenes when we evaluate the QuerySet. This could help us with the debug process and not only. The string representation of the <code>query</code> attribute of the QuerySet object is the SQL query that we are talking about. See the example below:</p>

<pre><code class="python hljs">In: str(User.objects.all().query)
Out: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"'
</code></pre>

<p>This technique will be used in further examples.</p>

<h4 id="section-and">How to do AND operation?</h4>

<p>As an <code>AND</code> operation example let's limit(<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#filter" target="_blank" rel="noopener">filter()</a>) users whose <code>first_name</code>  is equal to <strong>John</strong> and also make sure that they are active - <code>is_active</code> is true.</p>

<pre><code class="python hljs">qs1 = User.objects.filter(first_name="John", is_active=True)</code></pre>

<p> the same thing we can do by chaining multiple filters:</p>

<pre><code class="python hljs">qs2 = User.objects.filter(first_name="John").filter(is_active=True)</code></pre>

<p>alternatively, we can apply **&** operator on two or more QuerySets:</p>

<pre><code class="python hljs">qs3 = User.objects.filter(first_name="John") & User.objects.filter(is_active=True)</code></pre>

<p>and finally, we can use the tool <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django.db.models.Q" target="_blank" rel="noopener">Q</a> from <code>django.db.models</code>.</p>

<pre><code class="python hljs">qs4 = User.objects.filter(Q(first_name="John") & Q(is_active=True))</code></pre>

<p>It's worth saying that all QuerySet objects(qs1, qs2, qs3, qs4) will generate the same SQL query in the end. The comparison below proves that:</p>

<pre><code class="python hljs">In: str(qs1.query) == str(qs2.query) == str(qs3.query) == str(qs3.query)
Out: True
</code></pre>

<p>In SQL terms, they are evaluated to:</p>

<pre><code class="sql hljs">SELECT "auth_user"."id", 
   ...
   "auth_user"."date_joined" 
FROM "auth_user" 
WHERE ("auth_user"."first_name" = John AND "auth_user"."is_active" = True)
</code></pre>

<p>SQL query, all without exceptions.</p>

<h4 id="section-or">How to do OR operation?</h4>

<p>Very basic example of <code>OR</code> operation will be filtering users whose <code>first_name</code> is equal to **John** or **Jane**. We can achieve this with the help of Q:</p>

<pre><code class="python hljs">qs1 = User.objects.filter(Q(first_name="John") | Q(first_name="Jane"))</code></pre>

<p>or applying **|** (pipe) operator on two or more querysets :</p>

<pre><code class="python hljs">qs2 = User.objects.filter(first_name="John") | User.objects.filter(first_name="Jane")</code></pre>

<p>It's true that <code>qs1</code> and <code>qs2</code> have identical SQL queries:</p>

<pre><code class="python hljs">In: str(qs1.query) == str(qs2.query)
Out: True
</code></pre>

<p>and both produce:</p>

<pre><code class="sql hljs">SELECT "auth_user"."id", 
   ...
   "auth_user"."date_joined" 
FROM "auth_user" 
WHERE ("auth_user"."first_name" = John OR "auth_user"."first_name" = Jane)
</code></pre>

<p>SQL query.</p>

<h4 id="section-not-equal">How to do a not equal filtering?</h4>

<p>As an example, we will select all the users except ones whose <code>first_name</code> is equal to **John**:</p>

<pre><code class="python hljs">qs1 = User.objects.filter(~Q(first_name="John"))</code></pre>

<p>another way of doing the same query is using the <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#exclude" target="_blank" rel="noopener">exclude()</a> method:</p>

<pre><code class="python hljs">qs2 = User.objects.exclude(first_name="John")</code></pre>

<p>As you may guess, SQL queries are identical in this case too:</p>

<pre><code class="python hljs">In: str(qs1.query) == str(qs2.query)
Out: True
</code></pre>

<p>and the produced SQL query is:</p>

<pre><code class="sql hljs">SELECT "auth_user"."id", 
   ...
   "auth_user"."date_joined" 
FROM "auth_user" 
WHERE NOT ("auth_user"."first_name" = John)
</code></pre>

<h4 id="section-in">How to do IN filtering?</h4>

<p>A typical example could be filtering users by the given list of IDs. Below is an example with the <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#in" targte="_blank" rel="noopener">in</a> expression being used:</p>

<pre><code class="python hljs">qs = User.objects.filter(pk__in=[1, 4, 7])</code></pre>

<pre><code class="sql hljs">SELECT "auth_user"."id", 
   ...
   "auth_user"."date_joined" 
FROM "auth_user" 
WHERE "auth_user"."id" IN (1, 4, 7)
</code></pre>

<p>In some cases it might be benefical to use <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#in-bulk" target="_blank" rel="noopener">in_bulk()</a> method. 
<br>**in_bulk(id_list=None, field_name='pk')** takes a list of field values **(id_list)** and the **field_name** for those values, and returns a dictionary mapping each value to an instance of the object with the given field value. If **id_list** isn’t provided, all objects in the queryset are returned. <br>**IMPORTANT!** **field_name** must be a unique field, and it defaults to the primary key. <br> Example:
<p>

<pre><code class="python hljs">In: User.objects.in_bulk([1, 4, 7])
Out: {1: < User: John >, 4: < User: Jane >, 7: < User: Jemery >}</code></pre>

<h4 id="section-isnull">How to do IS NULL or IS NOT NULL queries?</h4>

<p>
As an example, we will select only those users whose <code>first_name</code> is not specified(in other words it is **NULL**):
</p>

<pre><code class="python hljs">qs = User.objects.filter(first_name__isnull=True)</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."first_name" IS NULL
</code></pre>

<p>the opposite QuerySet:<p>

<pre><code class="python hljs">qs = User.objects.filter(first_name__isnull=False)</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."first_name" IS NOT NULL
</code></pre>

<p>So, <code>isnull</code> takes either **True** or **False**, which correspond to SQL queries of **IS NULL** and **IS NOT NULL**, respectively.

<h4 id="section-like">How to do SQL “LIKE” equivalent queries?</h4>

<p>
The SQL **LIKE** operator is used in a WHERE clause to search for a specified pattern in a column.
There are two wildcards often used in conjunction with the LIKE operator:
</p>

<ul>

<li>
**%** - The percent sign represents zero, one, or multiple characters
</li>
<li>
**_** - The underscore represents a single character
</li>
</ul>

<p>We will cover different cases one by one. 
<br>The first case will be selecting users whose <code>first_name</code> starts with **Jo** string:</p>

<pre><code class="python hljs">qs = User.objects.filter(first_name__startswith="Jo")</code></pre>

<p>SQL equivalent: </p>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."first_name"::text LIKE Jo%
</code></pre>

<p>now let's select those users whose <code>last_name</code> ends with **yan** string:</p>

<pre><code class="python hljs">qs = User.objects.filter(last_name__endswith="yan")</code></pre>

<p>SQL equivalent: </p>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."last_name"::text LIKE %yan
</code></pre>

<p>To demonstrate the last example for the <code>%</code> wildcard, we will select users whose <code>last_name</code> contains **oh** string:</p>

<pre><code class="python hljs">qs = User.objects.filter(last_name__contains="oh")</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."last_name"::text LIKE %oh%
</code></pre>

<p>Unfortunatelly, there is no built-in tool for **_**(underscore wildcard). But, there is an alternative solution with the use of the <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#regex" target="_blank" rel="noopener">regex</a> lookup tool.</p>

<p>As an example, we will filter users whose <code>last_name</code> matches **D_e** patterns, which means that it should start with the letter **D** then follow with any **single** character and end with the letter **e**:
</p>

<pre><code class="python hljs">qs = User.objects.filter(last_name__regex=r"^D.e$")</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."last_name"::text ~ ^D.e$
</code></pre>

<p>As you can see, it's being converted to a regular expression syntax that is defined in the database backend.</p>

<p>All the tools in this section also support case insensitive lookups. Check 
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#startswith" target="_blank" rel="noopener">startswith</a>,
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#istartswith" target="_blank" rel="noopener">istartswith</a>,
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#endswith" target="_blank" rel="noopener">endswith</a>,
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#iendswith" target="_blank" rel="noopener">iendswith</a>,
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#contains" target="_blank" rel="noopener">contains</a>,
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#icontains" target="_blank" rel="noopener">icontains</a>,
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#regex" target="_blank" rel="noopener">regex</a>,
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#iregex" target="_blank" rel="noopener">iregex</a>
 in the official docs for the details.</p>

<h4 id="section-comparsion">How to do comparison(>, >=, <, <=) operations?</h4>

<p>
Getting all users, whose <code>id</code> is greater than(>) **3** integer:
</p>

<pre><code class="python hljs">qs = User.objects.filter(id__gt=3)</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."id" > 3
</code></pre>

<p>
Getting all users, whose <code>id</code> is less than(<) **4** integer:
</p>

<pre><code class="python hljs">qs = User.objects.filter(id__lt=4)</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."id" < 4
</code></pre>

<p>As you may guess, **gt** and **lt** are short aliases for **greater than** and **less than**, respectively.</p>

<p>And for doing **greater than or equal** or **less than or equal** lookups we just have to add **e - equal** at the end of the alias.
So, <code>gte</code> will be converted to <code>>=</code> and <code>lte</code> will be converted to <code><=</code>. More on this <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#gt" target="_blank" rel="noopener">here</a>.
</p>

<h4 id="section-between">How to do BETWEEN operation?</h4>

<p>
To implement <code>BETWEEN</code> operation we are going to use another Django's tool called <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#range" target="_blank" rel="noopener">range</a>. And we are going to filter users whose <code>date_joined</code>(datetime) value is in a specific date time range. Before building the QuerySet let's prepare two **timezone aware** datetime objects:
</p>

<pre><code class="python hljs">import pytz
from django.utils import timezone

start = timezone.make_aware(timezone.datetime(year=2019, month=1, day=1), pytz.utc)
end = timezone.make_aware(timezone.datetime(year=2019, month=12, day=31), pytz.utc)
</code></pre>

<p>the QuerySet: </p>

<pre><code class="python hljs">qs = User.objects.filter(date_joined__range=[start, end])</code></pre>

<p>SQL equivalent:</p>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
WHERE "auth_user"."date_joined" BETWEEN 2019-01-01 00:00:00+00:00 AND 2019-12-31 00:00:00+00:00
</code></pre>

<p>FYI, you can use range anywhere you can use BETWEEN in SQL queries - for dates, numbers, and even characters. **Note** that the end of the range is **inclusive**.</p>

<h4 id="section-limit">How to LIMIT the number of results in queryset?</h4>

<p>
To implement SQL’s LIMIT and OFFSET clauses we should use a subset of Python’s array-slicing syntax on a QuerySet object. The example below returns the first 10 users(**LIMIT 10**):
</p>


<pre><code class="python hljs">qs = User.objects.all()[:10]</code></pre>

<p>SQL equivalent:</p>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
LIMIT 10
</code></pre>

<p>
tenth through twentieth users(**LIMIT 10 OFFSET 10**):
</p>

<pre><code class="python hljs">qs = User.objects.all()[10:20]</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
LIMIT 10 OFFSET 10
</code></pre>

<p>At first glance you might think that this type of LIMIT OFFSET operations force to evaluate the QuerySet. But in general, slicing returns a new QuerySet object - it doesn’t evaluate the query. As we've noted at the beginning of this article, slices evaluate a QuerySet only if we use them **with the step parameter**. Both examples above are not evaluated  - new QuerySets are being returned instead. An example of slicing with the step could be returning a list of every second object of the first 10 users:
</p>

<pre><code class="python hljs">list_of_every_second = User.objects.all()[:10:2]</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
LIMIT 10
</code></pre>

<p>QuerySet for this operation is the same as for **LIMIT 10** one above, but immediate evaluation and **additional post-processing** happened in this case in order to return every second object from the list of 10 objects.</p>

<p>To retrieve a single user rather than a list, use an **index** instead of a **slice**. For example, this returns the first **User** in the database:</p>

<pre><code class="python hljs">In: User.objects.all()[0]
Out: < User: John >
</code></pre>

<p>SQL equivalent:</p>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
LIMIT 1
</code></pre>

<p>Note, that this approach will raise **IndexError** if there are no rows in the database.</p>

<p>It's **important** to note that negative indexing (i.e. <code>User.objects.all()[-1]</code>) is not supported on QuerySets.</p>
<p>The implemenaion of slicing/indexing is written inside of <code>__getitem__</code> method that you can find in <code>QuerySet</code> class located in <code>django.db.models.query</code> module.</p>

<h4 id="section-order">How to ORDER results with QuerySets?</h4>

<p>
To order a QuerySet you need to use the <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django.db.models.query.QuerySet.order_by" target="_blank" rel="noopener">order_by()</a> method. Additionally, you should pass the field(s) that are going to be used in sorting to that method:
</p>

<pre><code class="python hljs">qs = User.objects.order_by('date_joined')</code></pre>

<p>SQL equivalent:</p>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
ORDER BY "auth_user"."date_joined" ASC
</code></pre>

<p>Query will return the list of users ordered by <code>date_joined</code> field **ascending**. We can pass as many fields as we need, also, adding the <code>-</code>(dash) at the beginning of the field will order results in **descending** order. Example: </p>

<pre><code class="python hljs">qs = User.objects.order_by('date_joined', '-first_name')</code></pre>

<p>SQL equivalent:</p>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
ORDER BY "auth_user"."date_joined" ASC,
         "auth_user"."first_name" DESC
</code></pre>

<p><a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#reverse" targte="_blank" rel="noopnener">reverse()</a> method will reverse the existing order of QuerySet. Calling <code>reverse()</code> second time will restore the ordering back to the normal direction:</p>

<pre><code class="python hljs">qs = User.objects.order_by('date_joined', '-first_name').reverse()</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
ORDER BY "auth_user"."date_joined" DESC,
         "auth_user"."first_name" ASC
</code></pre>

<pre><code class="python hljs">In [1]: qs1 = User.objects.order_by('date_joined')
In [2]: qs2 = User.objects.order_by('date_joined').reverse().reverse()
In [3]: str(qs1.query) == str(qs2.query)
Out [3]: True
</code></pre>

<p>To order randomly, use <code>'?'</code> like below:</p>

<pre><code class="python hljs">qs = User.objects.order_by('?')</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
ORDER BY RANDOM() ASC
</code></pre>

<h4 id="section-single-object">How to get a single object from QuerySet?</h4>

<p>The first approach is to use indexing as we used in the LIMIT section above:<p>

<pre><code class="python hljs">In: User.objects.all()[0]
Out: < User: John >
</code></pre>

<p>Similiar QuerySet we can construct using the <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#django.db.models.query.QuerySet.get" target="_blank" rel="noopener">get()</a> method.
<code>get()</code> method returns the object matching the given lookup parameters, and raises <code>DoesNotExist</code> exception if there is no match. It raises <code>MultipleObjectsReturned</code> exception if more than one object was found. Example:</p>

<pre><code class="python hljs">In: User.objects.get(pk=1)
Out: < User: John >
</code></pre>

<p>Also, If you expect a QuerySet to return a single row, you can use <code>get()</code> without any arguments.</p>

<p>There are 4 other handy methods that exist to help us when we want to get a single row/object with some conditions.</p>

<p>
Indexing and get() approaches are "alarmic" in some cases and we might want to get the object if it exists, or <code>None</code> if it does not exist without catching any exceptions. And the 
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#first" target="_blank" rel="noopener">first()</a> method is very beneficial for that case:</p>

<pre><code class="python hljs">user = User.objects.order_by('date_joined', '-first_name').first()</code></pre>

<p>the equivalent example using indexing:</p>

<pre><code class="python hljs">try:
    user = User.objects.order_by('date_joined', '-first_name')[0]
except IndexError:
    user = None
</code></pre>

<p>The second method is the <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#last" target="_blank" rel="noopener">last()</a>, which works like <code>first()</code>, but returns the last object in the QuerySet:</p>

<pre><code class="python hljs">user = User.objects.order_by('first_name').last()</code></pre>

<pre><code class="python hljs">user = User.objects.order_by('first_name').reverse().first()</code></pre>

<p>SQLs for both queries will be the same.</p>

<p>It's worth to mention 2 other methods. <a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#latest" target="_blank" rel="noopener">latest()</a>, that returns the latest object in the table based on the given field(s) and 
<a href="https://docs.djangoproject.com/en/3.0/ref/models/querysets/#earliest" target="_blank" rel="noopener">earliest()</a> that works the same way but the opposite direction.</p>

<pre><code class="python hljs">user = User.objects.latest('date_joined', '-first_name')</code></pre>

<pre><code class="sql hljs">SELECT ...
FROM "auth_user" 
ORDER BY "auth_user"."date_joined" DESC,
         "auth_user"."first_name" ASC
</code></pre>

<p>Like <code>get()</code>, <code>earliest()</code> and <code>latest()</code> raise <code>DoesNotExist</code> if there is no object with the given parameters. As mentioned in the official docs, earliest() and latest() exist purely for **convenience** and **readability**.</p>

<h4 id="section-bonus-tip">Bonus Tip!</h4>

<p>
If you install and plug <a href="https://django-extensions.readthedocs.io/en/latest/index.html" target="_blank" rel="noopener">django_extensions</a> package to your project, you can output SQL queries in shell without manually printing them. There is a different shell command with special option(argument) for that:
</p>

<pre><code>$ python manage.py shell_plus --print-sql
>>> User.objects.first()
SELECT "auth_user"."id",
       "auth_user"."password",
       "auth_user"."last_login",
       "auth_user"."is_superuser",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."date_joined"
  FROM "auth_user"
 ORDER BY "auth_user"."id" ASC
 LIMIT 1
Execution time: 0.011151s [Database: default]
</code></pre>

<p>Note that <code>DEBUG</code> in project settings must be set to <code>True</code>.</p>

<p>You can also specify <code>SHELL_PLUS_PRINT_SQL</code> configuration option in settings to omit the above command-line option:<p>

<pre><code class="hljs python"># will print SQL queries in shell_plus
SHELL_PLUS_PRINT_SQL = True
</code></pre>

<h4 id="section-conclusion">Conclusion</h4>

<p>The QuerySet API is very big and there are a lot of other tools that we will cover in different posts. So keep subscribed to not miss them. </p>
