🔀 swagger-diff-ui
Drop-in Swagger UI for Django + DRF that diffs your live OpenAPI schema against a git branch or commit — then paints every changed endpoint as NEW · UPDATE · DELETE.
No Node. No separate SPA. Same /api/docs/ you already open — with a small baseline drawer on top.
Pick a baseline → Compare → see what changed.
✨ What you get
| Feature | What it does | |
|---|---|---|
| 🌿 | Branch / commit / relative ref | Baseline from git (main, SHA, HEAD~1, …) |
| ▶️ | Compare | Diff current schema vs that baseline |
| 🟢🟡🔴 | NEW / UPDATE / DELETE tags | On the left of every changed operation |
| 🎯 | Changed only | Hide unchanged APIs (toggle anytime) |
| 🔬 | Field-level UPDATE | Params, body, responses, schema props — colored dots |
| 🧱 | CI CLI | manage.py swagger_diff --ci exits non-zero on breaking changes |
⚙️ Baseline export uses a temporary git worktree +
manage.py spectacular. HTTP endpoints are intended for local / DEBUG only; the management command is safe for CI.
📦 Requirements
- Python 3.10+
- Django 4.2+
- Django REST Framework
- drf-spectacular
- A git checkout of your project (for branch/commit baselines)
🚀 Install
pip install swagger-diff-ui
From GitHub
pip install "git+https://github.com/Iman-Sharei/swagger-diff-ui.git"
🔌 Wire into Django
Same idea as spectacular: one app + a few routes.
1️⃣ Add the app
# settings — typically local / debug only
INSTALLED_APPS = [
# ...
"drf_spectacular",
"swagger_diff_ui",
]
2️⃣ Keep spectacular’s schema + include our URLs
# urls.py
from django.urls import include, path
from drf_spectacular.views import SpectacularAPIView
urlpatterns = [
# Real OpenAPI document (unchanged)
# ⚠️ URL name MUST be "api-schema" (or set SWAGGER_DIFF_SCHEMA_URL_NAME)
path("api/schema/", SpectacularAPIView.as_view(), name="api-schema"),
# Diff UI + helpers
path("api/", include("swagger_diff_ui.urls")),
]
The Swagger view resolves the schema via Django’s URL name api-schema. If your project uses a different name, either rename it or set:
SWAGGER_DIFF_SCHEMA_URL_NAME = "my-schema" # must match SpectacularAPIView's name=
3️⃣ Open the docs
http://127.0.0.1:8000/api/docs/
Done. ✅
🖱️ How to use
- Open
/api/docs/ - In the dark drawer, pick a baseline branch or commit
- Click Compare
- Changed endpoints get NEW / UPDATE / DELETE
- Open an UPDATE row for field-level diffs + colored Example Value dots
- Use Changed only / Show all APIs and Hide ▴ / Show ▾
Git refs accept branch names, SHAs, and relative history forms such as HEAD~1, main~3, or HEAD^.
⏱️ First compare for a given SHA can take a bit (worktree + schema export). Results cache under .schema-cache/ — keep that folder in .gitignore.
🧱 CI / CLI (breaking changes)
Run inside your Django project (same env as manage.py):
# Diff current schema vs previous commit; fail CI if breaking
python manage.py swagger_diff --ref HEAD~1 --ci
# Machine-readable report
python manage.py swagger_diff --ref origin/main --format json
# Fail only when you ask
python manage.py swagger_diff --ref HEAD~1 --fail-on-breaking
| Flag | Meaning |
|---|---|
--ref |
Baseline git ref (default HEAD~1) |
--format text|json |
Human summary or full JSON report |
--fail-on-breaking |
Exit 1 when breaking changes exist |
--ci |
Shorthand: text summary + fail on breaking |
--no-cache |
Skip .schema-cache and regenerate baseline |
Breaking detection is heuristic (removed operations/params/fields, newly required request fields, type/$ref changes, removed enum values, …). Use it as a CI gate, not a formal compatibility proof.
Example GitHub Actions step:
- name: OpenAPI breaking change check
run: python manage.py swagger_diff --ref origin/${{ github.base_ref }} --ci
🗺️ Routes
Assuming you included under api/:
| URL | Role |
|---|---|
/api/docs/ |
Swagger UI + schema-diff drawer |
/api/schema/ |
Your real OpenAPI schema (spectacular, name=api-schema) |
/api/swagger-diff/git-refs/ |
Branches + recent commits |
/api/swagger-diff/diff/?ref=… |
Diff report vs baseline |
/api/swagger-diff/baseline/?ref=… |
Raw baseline OpenAPI (optional) |
Diff helpers live under /api/swagger-diff/… so they never collide with /api/schema/.
⚙️ Settings & environment
| Knob | Default | Purpose |
|---|---|---|
DJANGO_SETTINGS_MODULE |
(required in real apps) | Used when exporting baseline schemas in a git worktree |
| Fallback if unset | config.settings.local |
Cookiecutter-style default for baseline subprocesses |
SWAGGER_DIFF_SETTINGS_MODULE |
— | Override settings module for baseline export only |
SWAGGER_DIFF_SCHEMA_URL_NAME |
api-schema |
URL name passed to Swagger UI for the live schema |
If your Django settings live elsewhere (e.g. myproject.settings.dev), set DJANGO_SETTINGS_MODULE as usual — or set SWAGGER_DIFF_SETTINGS_MODULE when the baseline worktree should load a different module than the running process.
🔒 Safety notes
- Git baseline HTTP APIs are gated to
DJANGO_ENV == "local"orDEBUG=True - The
swagger_diffmanagement command skips that gate so CI can run withDEBUG=False - Do not expose the HTTP helpers on production with
DEBUG=True - Prefer wiring
swagger_diff_uionly in local / staging settings (CLI can stay available whereverINSTALLED_APPSincludes the package)
🧪 Develop & test
pip install -e ".[dev]"
pytest -q
CI runs the same tests on Python 3.10–3.12 (see .github/workflows/ci.yml).
Sample project
cd examples/sample_project
python manage.py runserver
# → http://127.0.0.1:8000/api/docs/
See examples/sample_project/README.md.
Release notes: CHANGELOG.md.
📄 License
MIT · made for Django + DRF teams who live in /api/docs/
Metadata
Release files for swagger-diff-ui 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| swagger_diff_ui-0.1.2.tar.gz | 32.2 kB | Without provenance | Details for swagger_diff_ui-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| swagger_diff_ui-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for swagger_diff_ui-0.1.2-py3-none-any.whl |
Total release size: 64.4 kB
Release files / swagger_diff_ui-0.1.2.tar.gz
| Download URL | swagger_diff_ui-0.1.2.tar.gz |
|---|---|
| Size | 32.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b45f33d1dba5a26cf3232edee6dbe1b7f8e068889b272019d348ee75749bcdae
|
|
BLAKE2b-256 checksum How to use checksums |
c0b2e09a130e8b9657f628528ce39b1743c60396195faf48bea0cde32e85df43
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / swagger_diff_ui-0.1.2-py3-none-any.whl
| Download URL | swagger_diff_ui-0.1.2-py3-none-any.whl |
|---|---|
| Size | 32.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9cd2095a2c053183dcebf8b1cefaa942441c552bd84f7c4c4812e6ddfd40561f
|
|
BLAKE2b-256 checksum How to use checksums |
182ae1beca1f9b6c0ca8757434096c3647c349f210fca43a0ff5d227a3dc3d55
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Security for swagger-diff-ui 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.