Metadata-Version: 2.4
Name: django-query-budget
Version: 0.1.1
Summary: Database query budget enforcement for Django
Author: Jason Morton
License-Expression: MIT
Project-URL: Documentation, https://django-query-budget.readthedocs.io/en/latest/
Project-URL: Repository, https://github.com/jlmorton/django-query-budget
Project-URL: Issues, https://github.com/jlmorton/django-query-budget/issues
Project-URL: Changelog, https://django-query-budget.readthedocs.io/en/latest/changelog/
Keywords: django,database,query,budget,circuit-breaker,performance
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: Framework :: Django :: 6.0
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django>=4.2
Provides-Extra: redis
Requires-Dist: redis>=4.0; extra == "redis"
Provides-Extra: postgres
Requires-Dist: psycopg2-binary; extra == "postgres"
Provides-Extra: mysql
Requires-Dist: mysqlclient; extra == "mysql"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-django; extra == "dev"
Requires-Dist: redis; extra == "dev"
Provides-Extra: dev-all
Requires-Dist: pytest; extra == "dev-all"
Requires-Dist: pytest-django; extra == "dev-all"
Requires-Dist: redis; extra == "dev-all"
Requires-Dist: psycopg2-binary; extra == "dev-all"
Requires-Dist: mysqlclient; extra == "dev-all"
Dynamic: license-file

# Django Query Budget

[![PyPI version](https://img.shields.io/pypi/v/django-query-budget.svg)](https://pypi.org/project/django-query-budget/)
[![Python versions](https://img.shields.io/pypi/pyversions/django-query-budget.svg)](https://pypi.org/project/django-query-budget/)
[![Documentation](https://readthedocs.org/projects/django-query-budget/badge/?version=latest)](https://django-query-budget.readthedocs.io/en/latest/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

Database query budget enforcement for Django.

Define budgets on cumulative query runtime, query count, and per-query duration within rolling time windows. When a budget is exceeded, pluggable actions respond — log, reject, or custom.

## Features

- Budget enforcement via settings, decorators, or context managers
- Built-in `LOG` and `REJECT` actions with custom action support
- Async-safe hook system for observability
- SQL fingerprinting for query normalization
- Optional cluster-wide sync via Redis or database backends
- Works with Django 5.0+ (WSGI and ASGI)

## Installation

Install from [PyPI](https://pypi.org/project/django-query-budget/):

```bash
pip install django-query-budget
```

For Redis-based cluster sync:

```bash
pip install django-query-budget[redis]
```

## Quick start

```python
# settings.py
INSTALLED_APPS = ["django_query_budget", ...]

MIDDLEWARE = ["django_query_budget.middleware.QueryBudgetMiddleware", ...]

QUERY_BUDGET = {
    "default": {
        "total_runtime": "30m",
        "window": "5m",
        "action": "LOG",
    },
}
```

```python
# views.py
from django_query_budget import query_budget

@query_budget(total_runtime="10s", window="1m", action="REJECT")
def expensive_report(request):
    ...
```

## Documentation

Full documentation at **[django-query-budget.readthedocs.io](https://django-query-budget.readthedocs.io/en/latest/)**.

## License

MIT
