Django Queryset Feeler

Django Queryset Feeler

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.

Features

  • No settings.py, apps.py, or manage.py setup required. Just import the Feel class to get started.
  • Duck typing for Feel initialization. Pass views, functions, querysets, model instances, and more without configuration.
  • See syntax highlighted SQL generated by django’s ORM with Feel(app_view).sql.
  • Profile database queries with Feel(app_view).report.

Technologies

  • Django

About

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.