# Django SQL Stacktrace
[](https://github.com/jvacek/django-traceback-in-sql/actions/workflows/test.yml)
[](https://github.com/astral-sh/ruff)
[](https://github.com/astral-sh/uv)
[](https://pypi.python.org/pypi/django-traceback-in-sql)
[](https://github.com/astral-sh/django-traceback-in-sql/blob/main/LICENSE)
[](https://pypi.python.org/pypi/django-traceback-in-sql)
[](https://pypi.python.org/pypi/django-traceback-in-sql)
Annotates the stacktrace into the SQL query as a comment at runtime. Helpful for tracking down where queries are ran from within code, for example for analysing query counts in unit tests when trying to prevent N+1s.
## Compatibility
- Python 3.9–3.13
- Django 4.2, 5.2
- SQLite, PostgreSQL, MySQL
## Quick Examples
### Find N+1 queries in Django unit tests
```python
from django.contrib.auth import get_user_model
from django.test import TestCase
from sql_traceback import sql_traceback
User = get_user_model()
class Test(TestCase):
def test_something(self):
with sql_traceback(), self.assertNumQueries(0):
_ = User.objects.count()
```
If the assert gets triggered, you will see something like the following output:
```text
E AssertionError: 1 != 0 : 1 queries executed, 0 expected
E Captured queries were:
E 1. SELECT COUNT(*) AS `__count` FROM `auth_user`
E /*
E STACKTRACE:
E # /path/to/tests/test_test_test.py:12 in test_something
E */
```
### In pytest-django tests
The above equivalent would look like so
```python
import pytest
from django.contrib.auth import get_user_model
from sql_traceback import sql_traceback
User = get_user_model()
@pytest.mark.django_db
def test_something(django_assert_num_queries):
with sql_traceback(), django_assert_num_queries(0):
_ = User.objects.count()
```
and when `pytest` is ran with the `-v` flag, you will see the following in the output
```text
E Queries:
E ========
E
E SELECT COUNT(*) AS `__count` FROM `auth_user`
E /*
E STACKTRACE:
E # /path/to/tests/tests/test_test_test.py:12 in test_something
E */
```
### As a context manager
```python
from sql_traceback import sql_traceback
with sql_traceback():
user = User.objects.select_related('profile').get(id=1)
user.profile.do_something()
```
### As a decorator
```python
from sql_traceback import SqlTraceback
@SqlTraceback()
def get_users():
return User.objects.filter(is_active=True)
```
## Configuration
Optional settings in your Django `settings.py`:
```python
SQL_TRACEBACK_ENABLED = True # Enable/disable stacktracing (default: True)
SQL_TRACEBACK_MAX_FRAMES = 15 # Max number of stack frames (default: 15)
SQL_TRACEBACK_FILTER_SITEPACKAGES = True # Filter out third-party packages (e.g., **django**, requests, pluggy, etc.) (default: True)
SQL_TRACEBACK_FILTER_TESTING_FRAMEWORKS = True # Filter out pytest/unittest frames (pytest + unittest) (default: True)
SQL_TRACEBACK_FILTER_STDLIB = True # Filter out Python standard library frames (e.g., threading, contextlib, etc.) (default: True)
SQL_TRACEBACK_MIN_APP_FRAMES = 1 # Minimum application frames required (default: 1)
```
Raw data
{
"_id": null,
"home_page": null,
"name": "django-traceback-in-sql",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "debugging, django, sql, traceback",
"author": "Jonas Vacek",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/ec/3a/1ee7b985eba009e73e708eda0d73cbf3f70398df5554da3d7551f439920d/django_traceback_in_sql-0.2.0.tar.gz",
"platform": null,
"description": "# Django SQL Stacktrace\n\n[](https://github.com/jvacek/django-traceback-in-sql/actions/workflows/test.yml)\n[](https://github.com/astral-sh/ruff)\n[](https://github.com/astral-sh/uv)\n\n[](https://pypi.python.org/pypi/django-traceback-in-sql)\n[](https://github.com/astral-sh/django-traceback-in-sql/blob/main/LICENSE)\n[](https://pypi.python.org/pypi/django-traceback-in-sql)\n[](https://pypi.python.org/pypi/django-traceback-in-sql)\n\nAnnotates the stacktrace into the SQL query as a comment at runtime. Helpful for tracking down where queries are ran from within code, for example for analysing query counts in unit tests when trying to prevent N+1s.\n\n## Compatibility\n\n- Python 3.9\u20133.13\n- Django 4.2, 5.2\n- SQLite, PostgreSQL, MySQL\n\n## Quick Examples\n\n### Find N+1 queries in Django unit tests\n\n```python\nfrom django.contrib.auth import get_user_model\nfrom django.test import TestCase\nfrom sql_traceback import sql_traceback\n\n\nUser = get_user_model()\n\n\nclass Test(TestCase):\n def test_something(self):\n with sql_traceback(), self.assertNumQueries(0):\n _ = User.objects.count()\n```\n\nIf the assert gets triggered, you will see something like the following output:\n\n```text\nE AssertionError: 1 != 0 : 1 queries executed, 0 expected\nE Captured queries were:\nE 1. SELECT COUNT(*) AS `__count` FROM `auth_user`\nE /*\nE STACKTRACE:\nE # /path/to/tests/test_test_test.py:12 in test_something\nE */\n```\n\n### In pytest-django tests\n\nThe above equivalent would look like so\n\n```python\nimport pytest\nfrom django.contrib.auth import get_user_model\nfrom sql_traceback import sql_traceback\n\n\nUser = get_user_model()\n\n\n@pytest.mark.django_db\ndef test_something(django_assert_num_queries):\n with sql_traceback(), django_assert_num_queries(0):\n _ = User.objects.count()\n```\n\nand when `pytest` is ran with the `-v` flag, you will see the following in the output\n\n```text\nE Queries:\nE ========\nE\nE SELECT COUNT(*) AS `__count` FROM `auth_user`\nE /*\nE STACKTRACE:\nE # /path/to/tests/tests/test_test_test.py:12 in test_something\nE */\n```\n\n### As a context manager\n\n```python\nfrom sql_traceback import sql_traceback\n\nwith sql_traceback():\n user = User.objects.select_related('profile').get(id=1)\n user.profile.do_something()\n```\n\n### As a decorator\n\n```python\nfrom sql_traceback import SqlTraceback\n\n@SqlTraceback()\ndef get_users():\n return User.objects.filter(is_active=True)\n```\n\n## Configuration\n\nOptional settings in your Django `settings.py`:\n\n```python\nSQL_TRACEBACK_ENABLED = True # Enable/disable stacktracing (default: True)\nSQL_TRACEBACK_MAX_FRAMES = 15 # Max number of stack frames (default: 15)\nSQL_TRACEBACK_FILTER_SITEPACKAGES = True # Filter out third-party packages (e.g., **django**, requests, pluggy, etc.) (default: True)\nSQL_TRACEBACK_FILTER_TESTING_FRAMEWORKS = True # Filter out pytest/unittest frames (pytest + unittest) (default: True)\nSQL_TRACEBACK_FILTER_STDLIB = True # Filter out Python standard library frames (e.g., threading, contextlib, etc.) (default: True)\nSQL_TRACEBACK_MIN_APP_FRAMES = 1 # Minimum application frames required (default: 1)\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "Contextmanager for annotation the relevant stack trace to SQL queries as a comment",
"version": "0.2.0",
"project_urls": {
"Repository": "https://github.com/jvacek/django-traceback-in-sql"
},
"split_keywords": [
"debugging",
" django",
" sql",
" traceback"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "a44941752b1e9f9d12694483aa65bed53cc7233d1ba139adb470b5eea970ccd9",
"md5": "d002d6febac90306b7bf63791c300bf0",
"sha256": "a1298a8a83992bbc8efb0bc0339a5fe4ea230ce5d017fd189066210296a06bcc"
},
"downloads": -1,
"filename": "django_traceback_in_sql-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "d002d6febac90306b7bf63791c300bf0",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 18808,
"upload_time": "2025-10-15T08:52:46",
"upload_time_iso_8601": "2025-10-15T08:52:46.979262Z",
"url": "https://files.pythonhosted.org/packages/a4/49/41752b1e9f9d12694483aa65bed53cc7233d1ba139adb470b5eea970ccd9/django_traceback_in_sql-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "ec3a1ee7b985eba009e73e708eda0d73cbf3f70398df5554da3d7551f439920d",
"md5": "88c0e9e14f3d33f6d5115a99828932c9",
"sha256": "e2c528eb4c84bfcf80208febb06fc21306080750ec390c1a266e6369ee00b220"
},
"downloads": -1,
"filename": "django_traceback_in_sql-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "88c0e9e14f3d33f6d5115a99828932c9",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 12668,
"upload_time": "2025-10-15T08:52:48",
"upload_time_iso_8601": "2025-10-15T08:52:48.128789Z",
"url": "https://files.pythonhosted.org/packages/ec/3a/1ee7b985eba009e73e708eda0d73cbf3f70398df5554da3d7551f439920d/django_traceback_in_sql-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-15 08:52:48",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "jvacek",
"github_project": "django-traceback-in-sql",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "django-traceback-in-sql"
}