569π
See the docs FAQ: "How can I see the raw SQL queries Django is running?"
django.db.connection.queries
contains a list of the SQL queries:
from django.db import connection
print(connection.queries)
Querysets also have a query
attribute containing the query to be executed:
print(MyModel.objects.filter(name="my name").query)
Note that the output of the query is not valid SQL, because:
"Django never actually interpolates the parameters: it sends the query and the parameters separately to the database adapter, which performs the appropriate operations."
From Django bug report #17741.
Because of that, you should not send query output directly to a database.
If you need to reset the queries to, for example, see how many queries are running in a given period, you can use reset_queries
from django.db
:
from django.db import reset_queries
from django.db import connection
reset_queries()
# Run your query here
print(connection.queries)
>>> []
114π
Django-extensions have a command shell_plus with a parameter print-sql
./manage.py shell_plus --print-sql
In django-shell all executed queries will be printed
Example:
User.objects.get(pk=1)
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"
WHERE "auth_user"."id" = 1
Execution time: 0.002466s [Database: default]
<User: username>
- [Django]-Error: could not determine PostgreSQL version from '10.3' β Django on Heroku
- [Django]-How to make two django projects share the same database
- [Django]-Django: Multiple forms possible when using FormView?
71π
Take a look at debug_toolbar, itβs very useful for debugging.
Documentation and source is available at http://django-debug-toolbar.readthedocs.io/.
- [Django]-How do Django models work?
- [Django]-How to query as GROUP BY in Django?
- [Django]-Django-reversion and related model
41π
The query is actually embedded in the models API:
q = Query.objects.values('val1','val2','val_etc')
print(q.query)
- [Django]-Django-rest-framework returning 403 response on POST, PUT, DELETE despite AllowAny permissions
- [Django]-Django limit_choices_to for multiple fields with "or" condition
- [Django]-Is this the right way to do dependency injection in Django?
35π
No other answer covers this method, so:
I find by far the most useful, simple, and reliable method is to ask your database. For example on Linux for Postgres you might do:
sudo su postgres
tail -f /var/log/postgresql/postgresql-8.4-main.log
Each database will have slightly different procedure. In the database logs youβll see not only the raw SQL, but any connection setup or transaction overhead django is placing on the system.
- [Django]-How about having a SingletonModel in Django?
- [Django]-How can I get tox and poetry to work together to support testing multiple versions of a Python dependency?
- [Django]-Visual Editor for Django Templates?
21π
This is a much late answer but for the others are came here by searching.
I want to introduce a logging method, which is very simple; add django.db.backends
logger in settins.py
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
I am also using an environment variable to set the level.
So when I want to see the SQL queries I just set the environment variable, and debug log shows the actual queries.
- [Django]-Get the list of checkbox post in django views
- [Django]-Do I need Nginx with Gunicorn if I am not serving any static content?
- [Django]-Django: Reverse for 'detail' with arguments '('',)' and keyword arguments '{}' not found
18π
Though you can do it with the code supplied, I find that using the debug toolbar app is a great tool to show queries. You can download it from github here.
This gives you the option to show all the queries ran on a given page along with the time to query took. It also sums up the number of queries on a page along with total time for a quick review. This is a great tool, when you want to look at what the Django ORM does behind the scenes. It also have a lot of other nice features, that you can use if you like.
- [Django]-How to filter empty or NULL names in a QuerySet?
- [Django]-What is more efficient .objects.filter().exists() or get() wrapped on a try
- [Django]-Function decorators with parameters on a class based view in Django
18π
Another option, see logging options in settings.py described by this post
http://dabapps.com/blog/logging-sql-queries-django-13/
debug_toolbar slows down each page load on your dev server, logging does not so itβs faster. Outputs can be dumped to console or file, so the UI is not as nice. But for views with lots of SQLs, it can take a long time to debug and optimize the SQLs through debug_toolbar since each page load is so slow.
- [Django]-Django Cache cache.set Not storing data
- [Django]-Django-Bower + Foundation 5 + SASS, How to configure?
- [Django]-Access web server on VirtualBox/Vagrant machine from host browser?
12π
I developed an extension for this purpose, so you can easily put a decorator on your view function and see how many queries are executed.
To install:
pip install django-print-sql
To use as a context manager:
from django_print_sql import print_sql
# Set `count_only` to `True` will print the number of executed SQL statements only
with print_sql(count_only=False):
# Write the code you want to analyze in here,
# e.g., some complex foreign key lookup,
# or analyzing a DRF serializer's performance
for user in User.objects.all()[:10]:
user.groups.first()
To use as a decorator:
from django_print_sql import print_sql_decorator
@print_sql_decorator(count_only=False) # This works on class-based views as well
def get(request):
# Your view code here
GitHub: django-print-sql
- [Django]-Django: Arbitrary number of unnamed urls.py parameters
- [Django]-PHP Frameworks (CodeIgniter, Yii, CakePHP) vs. Django
- [Django]-Custom django admin templates not working
11π
If you make sure your settings.py file has:
django.core.context_processors.debug
listed inCONTEXT_PROCESSORS
DEBUG=True
- your
IP
in theINTERNAL_IPS
tuple
Then you should have access to the sql_queries
variable. I append a footer to each page that looks like this:
{%if sql_queries %}
<div class="footNav">
<h2>Queries</h2>
<p>
{{ sql_queries|length }} Quer{{ sql_queries|pluralize:"y,ies" }}, {{sql_time_sum}} Time
{% ifnotequal sql_queries|length 0 %}
(<span style="cursor: pointer;" onclick="var s=document.getElementById('debugQueryTable').style;s.disp\
lay=s.display=='none'?'':'none';this.innerHTML=this.innerHTML=='Show'?'Hide':'Show';">Show</span>)
{% endifnotequal %}
</p>
<table id="debugQueryTable" style="display: none;">
<col width="1"></col>
<col></col>
<col width="1"></col>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">SQL</th>
<th scope="col">Time</th>
</tr>
</thead>
<tbody>
{% for query in sql_queries %}
<tr class="{% cycle odd,even %}">
<td>{{ forloop.counter }}</td>
<td>{{ query.sql|escape }}</td>
<td>{{ query.time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
I got the variable sql_time_sum
by adding the line
context_extras['sql_time_sum'] = sum([float(q['time']) for q in connection.queries])
to the debug function in django_src/django/core/context_processors.py.
- [Django]-Do we need to upload virtual env on github too?
- [Django]-Where does pip install its packages?
- [Django]-Choose test database?
11π
Just to add, in Django, if you have a query like:
MyModel.objects.all()
do:
MyModel.objects.all().query.sql_with_params()
or:
str(MyModel.objects.all().query)
to get the SQL string.
- [Django]-Django custom management commands: AttributeError: 'module' object has no attribute 'Command'
- [Django]-Django gunicorn sock file not created by wsgi
- [Django]-Django.contrib.auth.logout in Django
9π
Django SQL Sniffer is another alternative for viewing (and seeing the stats of) raw executed queries coming out of any process utilising Django ORM. Iβve built it to satisfy a particular use-case that I had, which I havenβt seen covered anywhere, namely:
- no changes to the source code that the target process is executing (no need to register a new app in django settings, import decorators all over the place etc.)
- no changes to logging configuration (e.g. because Iβm interested in one particular process, and not the entire process fleet that the configuration applies to)
- no restarting of target process needed (e.g. because itβs a vital component, and restarts may incur some downtime)
Therefore, Django SQL Sniffer can be used ad-hoc, and attached to an already running process. The tool then "sniffs" the executed queries and prints them to console as they are executed. When the tool is stopped a statistical summary is displayed with outlier queries based on some possible metric (count, max duration and total combined duration).
Hereβs a screenshot of an example where I attached to a Python shell
You can check out the live demo and more details on the github page.
- [Django]-Django-allauth social account connect to existing account on login
- [Django]-What is the difference render() and redirect() in Django?
- [Django]-Django Cache cache.set Not storing data
4π
I put this function in a util file in one of the apps in my project:
import logging
import re
from django.db import connection
logger = logging.getLogger(__name__)
def sql_logger():
logger.debug('TOTAL QUERIES: ' + str(len(connection.queries)))
logger.debug('TOTAL TIME: ' + str(sum([float(q['time']) for q in connection.queries])))
logger.debug('INDIVIDUAL QUERIES:')
for i, query in enumerate(connection.queries):
sql = re.split(r'(SELECT|FROM|WHERE|GROUP BY|ORDER BY|INNER JOIN|LIMIT)', query['sql'])
if not sql[0]: sql = sql[1:]
sql = [(' ' if i % 2 else '') + x for i, x in enumerate(sql)]
logger.debug('\n### {} ({} seconds)\n\n{};\n'.format(i, query['time'], '\n'.join(sql)))
Then, when needed, I just import it and call it from whatever context (usually a view) is necessary, e.g.:
# ... other imports
from .utils import sql_logger
class IngredientListApiView(generics.ListAPIView):
# ... class variables and such
# Main function that gets called when view is accessed
def list(self, request, *args, **kwargs):
response = super(IngredientListApiView, self).list(request, *args, **kwargs)
# Call our function
sql_logger()
return response
Itβs nice to do this outside the template because then if you have API views (usually Django Rest Framework), itβs applicable there too.
- [Django]-Django β Clean permission table
- [Django]-Saving ModelForm error(User_Message could not be created because the data didn't validate)
- [Django]-How can i test for an empty queryset in Django?
3π
The following returns the query as valid SQL, based on https://code.djangoproject.com/ticket/17741:
def str_query(qs):
"""
qs.query returns something that isn't valid SQL, this returns the actual
valid SQL that's executed: https://code.djangoproject.com/ticket/17741
"""
cursor = connections[qs.db].cursor()
query, params = qs.query.sql_with_params()
cursor.execute('EXPLAIN ' + query, params)
res = str(cursor.db.ops.last_executed_query(cursor, query, params))
assert res.startswith('EXPLAIN ')
return res[len('EXPLAIN '):]
- [Django]-Django: sqlite for dev, mysql for prod?
- [Django]-Why is factory_boy superior to using the ORM directly in tests?
- [Django]-Django: How to check if the user left all fields blank (or to initial values)?
3π
I believe this ought to work if you are using PostgreSQL:
from django.db import connections
from app_name import models
from django.utils import timezone
# Generate a queryset, use your favorite filter, QS objects, and whatnot.
qs=models.ThisDataModel.objects.filter(user='bob',date__lte=timezone.now())
# Get a cursor tied to the default database
cursor=connections['default'].cursor()
# Get the query SQL and parameters to be passed into psycopg2, then pass
# those into mogrify to get the query that would have been sent to the backend
# and print it out. Note F-strings require python 3.6 or later.
print(f'{cursor.mogrify(*qs.query.sql_with_params())}')
- [Django]-Django gunicorn sock file not created by wsgi
- [Django]-How do I install psycopg2 for Python 3.x?
- [Django]-How to test "render to template" functions in django? (TDD)
3π
Thereβs another way thatβs very useful if you need to reuse the query for some custom SQL. Iβve used this in an analytics app that goes far beyond what Djangoβs ORM can do comfortably, so Iβm including ORM-generated SQL as subqueries.
from django.db import connection
from myapp.models import SomeModel
queryset = SomeModel.objects.filter(foo='bar')
sql_query, params = queryset.query.as_sql(None, connection)
This will give you the SQL with placeholders, as well as a tuple with query params to use. You can pass this along to the DB directly:
with connection.connection.cursor(cursor_factory=DictCursor) as cursor:
cursor.execute(sql_query, params)
data = cursor.fetchall()
- [Django]-Django Form File Field disappears on form error
- [Django]-How to change empty_label for modelForm choice field?
- [Django]-Copy a database column into another in Django
2π
Iβve made a small snippet you can use:
from django.conf import settings
from django.db import connection
def sql_echo(method, *args, **kwargs):
settings.DEBUG = True
result = method(*args, **kwargs)
for query in connection.queries:
print(query)
return result
# HOW TO USE EXAMPLE:
#
# result = sql_echo(my_method, 'whatever', show=True)
It takes as parameters a function (contains SQL queries) to inspect and args, kwargs needed to call that function. As the result, it returns what function returns and prints SQL queries in a console.
- [Django]-Http POST drops port in URL
- [Django]-Factory-boy create a list of SubFactory for a Factory
- [Django]-Folder Structure for Python Django-REST-framework and Angularjs
2π
To get result query from django to database(with correct parameter substitution)
you could use this function:
from django.db import connection
def print_database_query_formatted(query):
sql, params = query.sql_with_params()
cursor = connection.cursor()
cursor.execute('EXPLAIN ' + sql, params)
db_query = cursor.db.ops.last_executed_query(cursor, sql, params).replace('EXPLAIN ', '')
parts = '{}'.format(db_query).split('FROM')
print(parts[0])
if len(parts) > 1:
parts = parts[1].split('WHERE')
print('FROM{}'.format(parts[0]))
if len(parts) > 1:
parts = parts[1].split('ORDER BY')
print('WHERE{}'.format(parts[0]))
if len(parts) > 1:
print('ORDER BY{}'.format(parts[1]))
# USAGE
users = User.objects.filter(email='admin@admin.com').order_by('-id')
print_database_query_formatted(users.query)
Output example
SELECT "users_user"."password", "users_user"."last_login", "users_user"."is_superuser", "users_user"."deleted", "users_user"."id", "users_user"."phone", "users_user"."username", "users_user"."userlastname", "users_user"."email", "users_user"."is_staff", "users_user"."is_active", "users_user"."date_joined", "users_user"."latitude", "users_user"."longitude", "users_user"."point"::bytea, "users_user"."default_search_radius", "users_user"."notifications", "users_user"."admin_theme", "users_user"."address", "users_user"."is_notify_when_buildings_in_radius", "users_user"."active_campaign_id", "users_user"."is_unsubscribed", "users_user"."sf_contact_id", "users_user"."is_agree_terms_of_service", "users_user"."is_facebook_signup", "users_user"."type_signup"
FROM "users_user"
WHERE "users_user"."email" = 'admin@admin.com'
ORDER BY "users_user"."id" DESC
It based on this ticket comment: https://code.djangoproject.com/ticket/17741#comment:4
- [Django]-Handle `post_save` signal in celery
- [Django]-Are sessions needed for python-social-auth
- [Django]-'staticfiles' is not a valid tag library: Template library staticfiles not found
2π
To generate SQL for CREATE / UPDATE / DELETE / commands, which are immediate in Django
from django.db.models import sql
def generate_update_sql(queryset, update_kwargs):
"""Converts queryset with update_kwargs
like : queryset.update(**update_kwargs) to UPDATE SQL"""
query = queryset.query.clone(sql.UpdateQuery)
query.add_update_values(update_kwargs)
compiler = query.get_compiler(queryset.db)
sql, params = compiler.as_sql()
return sql % params
from django.db.models import sql
def generate_delete_sql(queryset):
"""Converts select queryset to DELETE SQL """
query = queryset.query.chain(sql.DeleteQuery)
compiler = query.get_compiler(queryset.db)
sql, params = compiler.as_sql()
return sql % params
from django.db.models import sql
def generate_create_sql(model, model_data):
"""Converts queryset with create_kwargs
like if was: queryset.create(**create_kwargs) to SQL CREATE"""
not_saved_instance = model(**model_data)
not_saved_instance._for_write = True
query = sql.InsertQuery(model)
fields = [f for f in model._meta.local_concrete_fields if not isinstance(f, AutoField)]
query.insert_values(fields, [not_saved_instance], raw=False)
compiler = query.get_compiler(model.objects.db)
sql, params = compiler.as_sql()[0]
return sql % params
Tests & usage
def test_generate_update_sql_with_F(self):
qs = Event.objects.all()
update_kwargs = dict(description=F('slug'))
result = generate_update_sql(qs, update_kwargs)
sql = "UPDATE `api_event` SET `description` = `api_event`.`slug`"
self.assertEqual(sql, result)
def test_generate_create_sql(self):
result = generate_create_sql(Event, dict(slug='a', app='b', model='c', action='e'))
sql = "INSERT INTO `api_event` (`slug`, `app`, `model`, `action`, `action_type`, `description`) VALUES (a, b, c, e, , )"
self.assertEqual(sql, result)
- [Django]-Problems extend change_form.html in django admin
- [Django]-What is more efficient .objects.filter().exists() or get() wrapped on a try
- [Django]-Django south migration β Adding FULLTEXT indexes
1π
from django.db import reset_queries, connection
class ShowSQL(object):
def __enter__(self):
reset_queries()
return self
def __exit__(self, *args):
for sql in connection.queries:
print('Time: %s\nSQL: %s' % (sql['time'], sql['sql']))
Then you can use:
with ShowSQL() as t:
some queries <select>|<annotate>|<update> or other
it prints
- Time: %s
- SQL: %s
- [Django]-Why there are two process when i run python manage.py runserver
- [Django]-Get list item dynamically in django templates
- [Django]-Negating a boolean in Django template
1π
You can use connection.queries
to get the raw SQL queries running in Django as shown below:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.db import connection
from django.http import HttpResponse
@transaction.atomic
def test(request):
Person.objects.create(name="John") # INSERT
qs = Person.objects.select_for_update().get(name="John") # SELECT FOR UPDATE
qs.name = "Tom"
qs.save() # UPDATE
qs.delete() # DELETE
for query in connection.queries: # Here
print(query)
return HttpResponse("Test")
Then, the raw queries are printed on console as shown below:
{'sql': 'INSERT INTO "store_person" ("name") VALUES (\'John\') RETURNING "store_person"."id"', 'time': '0.000'}
{'sql': 'SELECT "store_person"."id", "store_person"."name" FROM "store_person" WHERE "store_person"."name" = \'John\' LIMIT 21 FOR UPDATE', 'time': '0.000'}
{'sql': 'UPDATE "store_person" SET "name" = \'Tom\' WHERE "store_person"."id" = 179', 'time': '0.000'}
{'sql': 'DELETE FROM "store_person" WHERE "store_person"."id" IN (179)', 'time': '0.000'}
[24/Dec/2022 06:29:32] "GET /store/test/ HTTP/1.1" 200 9
Then, put reset_queries()
after Person.objects.select_for_update()
if you want to get only UPDATE
and DELETE
queries without INSERT
and SELECT FOR UPDATE
queries as shown below:
# "store/views.py"
from django.db import transaction
from .models import Person
from django.db import reset_queries
from django.db import connection
from django.http import HttpResponse
@transaction.atomic
def test(request):
Person.objects.create(name="John") # INSERT
qs = Person.objects.select_for_update().get(name="John") # SELECT FOR UPDATE
reset_queries() # Here
qs.name = "Tom"
qs.save() # UPDATE
qs.delete() # DELETE
for query in connection.queries: # Here
print(query)
return HttpResponse("Test")
Then, only UPDATE
and DELETE
queries are printed without INSERT
and SELECT FOR UPDATE
queries as shown below:
{'sql': 'UPDATE "store_person" SET "name" = \'Tom\' WHERE "store_person"."id" = 190', 'time': '0.000'}
{'sql': 'DELETE FROM "store_person" WHERE "store_person"."id" IN (190)', 'time': '0.000'}
[24/Dec/2022 07:00:01] "GET /store/test/ HTTP/1.1" 200 9
- [Django]-Django annotation with nested filter
- [Django]-Django: using more than one database with inspectdb?
- [Django]-Missing Table When Running Django Unittest with Sqlite3
0π
For those who are looking just the outcome from a query itself there is an easiest way:
Supposing we have a model called Musico
:
class Musico(models.Model):
INSTRUMENTOS = [
('violao', 'ViolΓ£o'),
('piano', 'Piano'),
('cavaquinho', 'Cavaquinho'),
]
usuario = models.OneToOneField(User, on_delete=models.DO_NOTHING, null=True)
primeiro_nome = models.CharField(max_length=120)
sobrenome = models.CharField(max_length=120, null=True, blank=True)
tipo_instrumento = models.CharField(choices=INSTRUMENTOS, max_length=200)
idade = models.IntegerField(null=True, blank=True)
def __str__(self):
return f"Musico: {self.primeiro_nome}"
To check the raw sql query would be like this:
>>> str(Musico.objects.all().query)
'SELECT "model_lesson_app_musico"."id", "model_lesson_app_musico"."usuario_id", "model_lesson_app_musico"."primeiro_nome", "model_lesson_app_musico"."sobrenome", "model_lesson_app_musico"."tipo_instrumento", "model_lesson_app_musico"."idade" FROM "model_lesson_app_musico"'
- [Django]-Extend base.html problem
- [Django]-Django: using more than one database with inspectdb?
- [Django]-What is the difference between cached_property in Django vs. Python's functools?
0π
Modifying your settings.py
file:
# settings.py
LOGGING = {
'version': 1,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {message}',
'style': '{',
},
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
},
}
Then make sure that your application is running in DEBUG mode,
# settings.py
DEBUG = True
Run your app now and you will see SQL queries printed to the console.
- [Django]-How do I deploy Django on AWS?
- [Django]-Http POST drops port in URL
- [Django]-How can I serialize a queryset from an unrelated model as a nested serializer?
-1π
View Queries using django.db.connection.queries
from django.db import connection
print(connection.queries)
Access raw SQL query on QuerySet object
qs = MyModel.objects.all()
print(qs.query)
- [Django]-Python 3 list(dictionary.keys()) raises error. What am I doing wrong?
- [Django]-Django models avoid duplicates
- [Django]-Get object by field other than primary key
-1π
For Django 2.2:
As most of the answers did not helped me much when using ./manage.py shell
. Finally i found the answer. Hope this helps to someone.
To view all the queries:
from django.db import connection
connection.queries
To view query for a single query:
q=Query.objects.all()
q.query.__str__()
q.query
just displaying the object for me.
Using the __str__()
(String representation) displayed the full query.
- [Django]-In a Django form, how do I make a field readonly (or disabled) so that it cannot be edited?
- [Django]-How to produce a 303 Http Response in Django?
- [Django]-Is there a way to filter a queryset in the django admin?
-1π
Several great answers here already.
One more way.
In test, do something like this:
with self.assertNumQueries(3):
response = self.client.post(reverse('payments:pay_list'))
# or whatever
If the number of queries is wrong, the test fails and prints all the raw SQL queries in the console.
Also, such tests help to control that the number of SQL queries does not grow as the code changes and the database load does not get excessive.
- [Django]-Why is factory_boy superior to using the ORM directly in tests?
- [Django]-Django-nonrel + Django-registration problem: unexpected keyword argument 'uidb36' when resetting password
- [Django]-How to run celery as a daemon in production?