As Django developers, we work mostly with the object-oriented Django ORM interface when querying data from our databases. However, under the hood, the Django ORM constructs SQL queries to interact with the database.
It can be useful to view the raw SQL for debugging performance issues or gaining a deeper understanding of how the ORM works. The Django ORM provides straightforward methods for this SQL introspection.
Examining Queries with str()
The simplest way to peek at the SQL is by casting the ORM’s QuerySet
object to a string. For example:
str(MyModel.objects.filter(name__icontains="foo"))
This will display the full text of the query that would be run, including parameters bound to the query.
However, a string representation of the query contains parameterized values rather than the actual data. So it won’t show the real values used in the query. Still, str()
gives a quick overview of the query structure.
Inspecting SQL with query
The QuerySet
class also provides a query
attribute that holds a django.db.connection.queries.Query
object representing the current query.
We can access this Query
instance directly:
query = MyModel.objects.filter(name__icontains="foo").query
print(query)
The Query
class has numerous attributes that give detailed metadata about the state of the current query. Some useful attributes include:
sql
– The actual SQL string that will be sent to the databaseparams
– The parameterized parameters that will be bound to the querytables
– A list of tables involvedwhere
– The parsed WHERE clause of the query
Overall, query
provides lower-level programmatic access to introspect the query.
Logging Queries during Requests
Writing print()
statements each time can be verbose. Instead, Django can automatically log all SQL queries run during a request for easy debugging.
In settings.py, add:
LOGGING = {
'loggers': {
'django.db.backends': {
'level': 'DEBUG',
'handlers': ['console']
}
}
}
This will output all SQL queries to the console as they execute. The log output will contain the full text of the query, exact parameters used, and query duration.
When to Inspect SQL Queries
Here are some common use cases for inspecting SQL queries:
- Finding slow queries for optimization using
EXPLAIN
- Verifying table joins are as expected
- Inspecting the exact SQL syntax dialect emitted for a database
- Learning more about advanced ORM behavior
Being able to inspect the raw SQL can deepen your grasp of Django DB operations. Both str()
and query
are easy enough to use anytime curiosity strikes while debugging or developing!