Get a better feel for how django is querying your database. django-queryset-feeler (dqf) is a Command line tool for convenient SQL logging and query summarization. No configuration required.
settings.py
, apps.py
, or manage.py
setup required. Just import the Feel
class to get started. Feel
initialization. Pass views, functions, querysets, model instances, and more without configuration. Feel(app_view).sql
.Feel(app_view).report
.Generated SQL is pulled from the django.db.connection
object which stores query data in debug mode. From these data raw SQL is syntax highlighted using pygments
and query counts and the number of tables accessed can be summarized. Query times are measured by averaging a configurable number of database accesses.
Sample dqf usage.
from django_queryset_feeler import Feel
from app.views import pizza_list_view
feel = Feel(pizza_list_view)
print(f'query count: {feel.count}')
print(f'average duration: {feel.time} s')
print(feel.sql)
Sample dqf output.
'query count: 4'
'average duration: 0.00023 s'
SELECT "app_pizza"."id",
"app_pizza"."name",
FROM "app_pizza"
SELECT "app_topping"."id",
"app_topping"."name",
"app_topping"."vegetarian"
FROM "app_topping"
WHERE "app_topping"."id" = '0'
SELECT "app_topping"."id",
"app_topping"."name",
"app_topping"."vegetarian"
FROM "app_topping"
WHERE "app_topping"."id" = '1'
SELECT "app_topping"."id",
"app_topping"."name",
"app_topping"."vegetarian"
FROM "app_topping"
WHERE "app_topping"."id" = '2'
The best feature of dqf is its ability to identify what type of object is being profiled. During the __init__
method of the Feel
class the first namespace argument (the ‘thing’) is identified and instructions for running that particular ‘thing’ are attached. Django-queryset-feeler can profile model instsances, querysets, function-based views, class-based views, django-rest-framework (DRF) serializers, DRF API views, or regular functions.
Views are profiled using an empty GET
request generated from the django or django-rest-framework testing libraries. An optional request
parameter can also be supplied during initialization.
Django querysets will fetch results from their ._result_cache
property to avoid rerunning queries. To ensure that a query is always run a django.db.models.query.ModelIterable
class is instantiated from the queryset and transformed into a list.
Model instances are requeried by simply calling their .refresh_from_db()
method.
Django-rest-framework serializers are profiled by calling .objects.all()
on the model pulled from the serializer’s .Meta.model
property and passing that queryset to the serializer. This is useful for finding N+1 problems when serializers traverse table relationships. The exact queryset being passed to the serializer is not yet configurable.
Note that dqf will only profile the default database.