Metadata-Version: 2.4
Name: djo
Version: 0.2.2
Summary: Drop-in interactive API docs for Django — Swagger UI, FastAPI-style, with zero decorators and zero extra dependencies
Project-URL: Homepage, https://github.com/NEFORCEO/djo
Project-URL: Documentation, https://djo.readthedocs.io
Project-URL: Repository, https://github.com/NEFORCEO/djo
Project-URL: Issues, https://github.com/NEFORCEO/djo/issues
Author-email: NEFORCEO <n7for8572@gmail.com>
Maintainer-email: NEFORCEO <n7for8572@gmail.com>
License: MIT
License-File: LICENSE
Keywords: api,autodoc,django,docs,openapi,rest,swagger,swagger-ui
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.2
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
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 :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: django>=5.2.15
Provides-Extra: dev
Requires-Dist: mkdocs-material>=9.5.0; extra == 'dev'
Requires-Dist: mkdocs>=1.6.0; extra == 'dev'
Requires-Dist: pre-commit>=4.0.0; extra == 'dev'
Requires-Dist: pymdown-extensions>=10.21.3; extra == 'dev'
Requires-Dist: pytest-django>=4.9.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.15.15; extra == 'dev'
Description-Content-Type: text/markdown

<p align="center">
  <img src="https://static.djangoproject.com/img/icon-touch.e4872c4da341.png" style="border-radius:20px; width:120">
</p>
<p align="center">
    <em>Drop-in interactive API docs for Django — Swagger UI, FastAPI-style, with zero decorators and zero extra dependencies.</em>
</p>
<p align="center">
<a href="https://github.com/NEFORCEO/djo/actions/workflows/publish.yml" target="_blank">
    <img src="https://github.com/NEFORCEO/djo/actions/workflows/publish.yml/badge.svg" alt="Publish">
</a>
<a href="https://pypi.org/project/djo" target="_blank">
    <img src="https://img.shields.io/pypi/v/djo?color=%2334D058&label=pypi%20package" alt="Package version">
</a>
<a href="https://pypi.org/project/djo" target="_blank">
    <img src="https://img.shields.io/pypi/dm/djo?color=%2334D058&label=downloads" alt="Monthly downloads">
</a>
</p>
<p align="center">
<a href="https://www.python.org/" target="_blank">
    <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/NEFORCEO/djo/master/docs/endpoints/python.json" alt="Python">
</a>
<a href="https://www.djangoproject.com/" target="_blank">
    <img src="https://img.shields.io/badge/django-5.2%2B-0C4B33" alt="Django">
</a>
<a href="https://github.com/NEFORCEO/djo/blob/master/LICENSE" target="_blank">
    <img src="https://img.shields.io/github/license/NEFORCEO/djo?color=%2334D058" alt="License">
</a>
</p>
<p align="center">
<a href="https://github.com/NEFORCEO/djo" target="_blank">
    <img src="https://img.shields.io/github/stars/NEFORCEO/djo?style=social" alt="GitHub Stars">
</a>
</p>

---

**Documentation**: <a href="https://djo.readthedocs.io" target="_blank">https://djo.readthedocs.io</a>

**Source Code**: <a href="https://github.com/NEFORCEO/djo" target="_blank">https://github.com/NEFORCEO/djo</a>

---

djo turns any Django project into a self-documenting API. Add one line to `INSTALLED_APPS` and a full Swagger UI shows up at `/docs` — no urls.py edits, no serializers, no decorators on your views. It walks your project's own `urlpatterns` and builds the OpenAPI schema from what it finds.

Key features:

- **Zero config** — the only thing you touch is `INSTALLED_APPS`. No `urls.py` changes, no middleware to wire up by hand.
- **Automatic** — paths, path parameters and HTTP methods are all inferred by walking the URLconf and the views it points to. Nothing to decorate, nothing to register.
- **Typed path params** — `<int:pk>`, `<uuid:token>`, `<slug:handle>` are mapped to real OpenAPI types straight from Django's own path converters.
- **Query params** — `request.GET.get("page", 1)` / `request.GET["tag"]` style access is picked up automatically, with type and required-ness inferred from how it's read.
- **Smart request bodies** — instead of a blank `{}`, djo reads a handler's source for `request.POST.get(...)` / `request.data[...]` style access and pre-fills the example with the fields it actually uses.
- **DRF serializer aware** — if a view declares `serializer_class`, djo reads the real fields straight off it (types, `required`, `read_only`/`write_only`, `choices`) instead of guessing from source.
- **Auth-aware** — `permission_classes`, `authentication_classes` and `LoginRequiredMixin` are detected automatically and surfaced as a Swagger **Authorize** button (cookie or bearer, depending on what the view uses).
- **Error responses** — status codes referenced via `status=404`, `status.HTTP_400_BAD_REQUEST`, or raised via `Http404`/DRF exceptions are added to the schema alongside the success response.
- **Interactive** — "Try it out" works against your real endpoints out of the box; the CSRF cookie is forwarded automatically for unsafe methods.
- **No extra dependencies** — pure Django. No Pydantic, no DRF required (though it plays nicely with DRF views if you have them).

## Requirements

Python 3.10+, Django 5.2+.

## Installation

```console
$ pip install djo
```

## Example

Add `"djo"` to `INSTALLED_APPS`:

```python
INSTALLED_APPS = [
    ...,
    "djo",
]
```

That's it. Run your project as usual:

```console
$ python manage.py runserver
```

### Check it

Go to <a href="http://127.0.0.1:8000/docs" target="_blank">http://127.0.0.1:8000/docs</a>.

You will see the automatic interactive API documentation, generated straight from your `urlpatterns`:

<img src="docs/media/swagger.png">

Expand any route to inspect path parameters and, where djo can infer them, request body fields. Click **Try it out** to execute the request for real and see the actual response — session auth and CSRF are handled for you.

## Configuration

Everything is optional — djo works with sane defaults out of the box. Override title, version, description, or the docs paths themselves via a `DJO` dict in `settings.py`:

```python
DJO = {
    "TITLE": "My API",
    "VERSION": "1.0.0",
    "DESCRIPTION": "Internal API for the mobile app.",
    "DOCS_URL": "/docs",
    "OPENAPI_URL": "/openapi.json",
}
```

## How it works

- `DjangoAPIConfig.ready()` prepends `djo.middleware.DjangoAPIMiddleware` to `settings.MIDDLEWARE` the moment the app is loaded — before Django builds its middleware chain — which is what lets a single `INSTALLED_APPS` entry serve `/docs` and `/openapi.json` with no `urls.py` changes.
- The middleware intercepts those two paths ahead of normal URL resolution; every other request passes straight through untouched.
- `djo/generator.py` walks `get_resolver().url_patterns` recursively, resolving `path()` converters into OpenAPI parameter types and reading each view's docstring for a summary.
- HTTP methods are inferred from class-based views (Django's `View` or DRF's `APIView`/`api_view`) by checking which handlers they actually implement; plain function-based views default to `GET`.
- Request/response bodies prefer a view's declared `serializer_class` (its fields are read directly, nothing is sent over the network) and fall back to a light, best-effort read of the handler's own source — pattern matching for body/query access, no execution of your views.
- Auth requirements and error status codes are inferred the same way: straight off class attributes for permissions/authentication, and off the handler's source for raised exceptions and explicit status codes.

## Try the demo project

The repo ships a throwaway Django project under [`test/`](test) wired up with a couple of sample endpoints, just to poke at the Swagger UI:

```console
$ cd test
$ python manage.py runserver
```

Then open `http://127.0.0.1:8000/docs`.

