A Django reusable package to manage Architectural Decision Records (ADR).
Warning: This package is not production ready. APIs and data models may change between versions.
- Django Admin interface to create and manage ADRs
- HTML list and detail views with status filtering
- Read-only REST API (Django REST Framework) with pre-rendered Markdown HTML fields
- Management command
create_adrto create ADRs from the CLI, with optional--supersedesto mark an existing ADR as superseded in one step - Management command
export_adrsto export all ADRs as Markdown files - Markdown support for context, decision, and consequences fields
- Internationalization (i18n) support — English locale included
pip install django-adrAdd to INSTALLED_APPS:
INSTALLED_APPS = [
...
"django_adr",
]Include the URLs:
from django.urls import include, path
urlpatterns = [
...
path("adrs/", include("django_adr.urls", namespace="django_adr")),
]Run migrations:
python manage.py migrateVisit /admin/django_adr/adr/ to manage ADRs through the Django admin.
/adrs/— list all ADRs/adrs/?status=accepted— filter by status/adrs/<number>/— view a single ADR
GET /adrs/api/adrs/— list all ADRsGET /adrs/api/adrs/<number>/— retrieve a single ADR
Create a new ADR:
python manage.py create_adr "Use PostgreSQL" \
--context="We need a relational database." \
--decision="Use PostgreSQL." \
--consequences="Team must know SQL."Create a new ADR and supersede an existing one in a single step:
python manage.py create_adr "Use CockroachDB" --supersedes=3This creates the new ADR and automatically marks ADR-0003 as Superseded.
Export all ADRs as Markdown files:
python manage.py export_adrs --output-dir=docs/adrEach ADR is written to <output-dir>/<number>-<slug>.md.
| Status | Description |
|---|---|
proposed |
Under discussion |
accepted |
Agreed and in effect |
deprecated |
No longer relevant |
superseded |
Replaced by a newer ADR |
rejected |
Considered and not adopted |
The HTML views and REST API are public by default. The package does not enforce any authentication strategy — that is left to the host project.
HTML views — in urls.py, wrap the URL include with login_required:
from django.contrib.auth.decorators import login_required
from django.urls import include, path
urlpatterns = [
path("adrs/", login_required(include("django_adr.urls", namespace="django_adr"))),
]REST API — set DEFAULT_PERMISSION_CLASSES in settings.py:
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
}Or scope it to the ADR router only by subclassing ADRViewSet:
from django_adr.api import ADRViewSet
from rest_framework.permissions import IsAuthenticated
class ProtectedADRViewSet(ADRViewSet):
permission_classes = [IsAuthenticated]All user-facing strings are translatable. The package ships with an English locale. To generate translations for your project:
python manage.py makemessages -l itEnsure USE_I18N = True in your project settings.
MIT