Metadata-Version: 2.4
Name: show-db-queries
Version: 1.0.0
Summary: A lightweight context manager to print and inspect Django DB queries during development and tests.
Project-URL: Homepage, https://github.com/levi/show-db-queries
Project-URL: Issues, https://github.com/levi/show-db-queries/issues
Author: Levi
License: MIT License
        
        Copyright (c) 2025 Levi Mann
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
License-File: LICENSE
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4
Classifier: Framework :: Django :: 5
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: <3.14,>=3.9
Requires-Dist: django>=4.2
Requires-Dist: sqlparse>=0.5.3
Description-Content-Type: text/markdown

# show-db-queries

A lightweight context manager to print and inspect Django database queries during development and tests. Debug query issues without the overhead of Django Debug Toolbar or Silk, with granular control over exactly which code blocks you want to inspect.

## Installation

```bash
pip install show-db-queries
# or
uv pip install show-db-queries
```

## Compatibility

| | Supported versions |
|---|---|
| Python | 3.9 – 3.13 |
| Django | 4.2, 5.0, 5.1, 5.2 |

## Quickstart

Wrap any code block to see every SQL query it executes:

```python
from show_db_queries import show_queries

with show_queries():
    User.objects.filter(is_active=True)
```

Output:

```
Queries:

0. 0.042 ms
--------------------------------------------------------------------------------
SELECT "auth_user"."id", "auth_user"."username", ...
  FROM "auth_user"
 WHERE "auth_user"."is_active" = true;

Queries executed: 1
```

## Usage

### Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `connection` | Django connection | `None` | Database connection to monitor. Defaults to `DEFAULT_DB_ALIAS`. |
| `print` | `bool` | `True` | Print queries to stdout when the block exits. |
| `color` | `bool` | `True` | Syntax-highlight SQL with ANSI colors for terminal output. |
| `file` | `str` | `None` | Write queries to a file in SQL comment format (colors disabled in file). |
| `stacktrace` | `bool` | `False` | Attach Python stacktraces to each query for source attribution. |
| `threshold` | `float` | `None` | Only show queries taking >= this many milliseconds. |

The previous long parameter names (`db_connection`, `print_queries`, `colorize`, `file_path`, `include_stacktrace`, `query_time_threshold`) are still accepted for backward compatibility.

### Capture queries silently

Disable printing and access results programmatically:

```python
ctx = show_queries(print=False)
with ctx:
    User.objects.create(username="test")

formatted_sql = ctx.get_queries(colorize=False)
print(f"Total queries: {ctx.final_queries}")
```

### Monitor a specific database connection

```python
from django.db import connections

replica = connections["replica"]
with show_queries(connection=replica):
    User.objects.using("replica").all()
```

### Write queries to a file

Queries are written in SQL format with comments for easy reading:

```python
with show_queries(file="/tmp/queries.sql"):
    Order.objects.select_related("customer").filter(status="pending")
```

### Include stacktraces

Find exactly where each query originates in your code:

```python
with show_queries(stacktrace=True):
    User.objects.get(pk=1)
```

Output includes the Python call stack for each query:

```
0. 0.035 ms
--------------------------------------------------------------------------------
SELECT ... FROM "auth_user" WHERE "auth_user"."id" = 1;

File "myapp/views.py", line 42, in get_user
    User.objects.get(pk=1)
```

### Filter slow queries

Only display queries above a time threshold (in milliseconds):

```python
with show_queries(threshold=50.0):
    # Only queries taking >= 50ms will appear
    process_large_dataset()
```

### Spot N+1 query problems

Compare query counts before and after optimization:

```python
# Before: N+1 queries
with show_queries():
    for book in Book.objects.all():
        print(book.author.name)
# Queries executed: 101

# After: single query with join
with show_queries():
    for book in Book.objects.select_related("author"):
        print(book.author.name)
# Queries executed: 1
```

### Use in tests

```python
class TestOrderCreation(TestCase):
    def test_query_count(self):
        ctx = show_queries(print=False)
        with ctx:
            create_order(user=self.user, item=self.item)
        self.assertLessEqual(ctx.final_queries, 3)
```

### Django settings

Set project-wide defaults so you don't have to pass the same options every time:

```python
# settings.py
SHOW_DB_QUERIES = {
    "file": "/tmp/queries.sql",
    "color": False,
    "stacktrace": True,
}
```

Any key matching a constructor parameter (`print`, `color`, `file`, `stacktrace`, `threshold`) can be included. Explicit arguments passed to `ShowDBQueries()` or `show_queries()` always take precedence over these defaults.

Optionally configure the Pygments color theme used for syntax highlighting:

```python
# settings.py
CODE_FORMAT_STYLE = "monokai"  # any Pygments style name
```

## Contributing

### Prerequisites

- Python 3.9+
- [uv](https://docs.astral.sh/uv/) (for dependency management)
- [just](https://github.com/casey/just) (optional, for task running)

### Local setup

```bash
git clone https://github.com/levi/show-db-queries.git
cd show-db-queries
uv sync
```

### Running tests

```bash
# Run all tests
uv run pytest

# Run with verbose output
uv run pytest -v

# Run a specific test
uv run pytest tests/test_context_managers.py::TestShowDBQueries::test_query

# Run with coverage report
uv run pytest --cov --cov-config=pyproject.toml --cov-report=html
open htmlcov/index.html
```

Or using `just`:

```bash
just test
just test -v
just test_with_coverage
```

### Linting and formatting

```bash
# Lint
uv run ruff check

# Format
uv run ruff format

# Run all checks (format + lint + test)
just pre_commit
```

### Making changes

1. Create a branch from `main`.
2. Make your changes.
3. Run `just pre_commit` to verify formatting, linting, and tests pass.
4. Submit a pull request.

### Releasing

Versioning and publishing is handled via the justfile and GitHub Actions:

```bash
just version_bump patch  # or minor, major
git push --follow-tags
```

Then create a release on [GitHub](https://github.com/levi/show-db-queries/releases) to trigger the PyPI publish workflow.

## License

MIT