Reusable Django backend foundation with auth, monitoring, privacy, security and project scaffolding
Project description
nimoh-be-django-base
Python ≥ 3.12 · Django ≥ 5.1, < 6.0 · v0.1.0 · MIT
A reusable Django backend foundation providing production-ready authentication, monitoring, privacy (GDPR), security headers, and interactive project-scaffolding tooling. Extract your boilerplate once; wire it into any Django project in minutes.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- CLI —
nimoh-base - Extending the User Model
- URL Reference
- Celery Setup
- Email Template Overrides
- Configuration Reference
- Architecture Decisions
- Further Reading
- License
Features
| Area | What you get |
|---|---|
| Authentication | JWT (access + refresh), rotating refresh tokens, device sessions, MFA (TOTP), email verification, HIBP password-breach checking, account-lock after failed attempts, audit logging |
| Monitoring | HTTP/DB performance-metrics middleware, health-check endpoints (/health/, /health/ready/), optional DB persistence |
| Privacy / GDPR | PrivacyProfile per user, consent records, data-processing log, GDPR data-export endpoint |
| Core | Abstract base models (TimeStampedModel, SoftDeleteModel), security-headers middleware, SQL-injection guard, custom DRF throttling classes, standardised exception handler |
| Config helpers | NimohBaseSettings — composable blocks for INSTALLED_APPS, MIDDLEWARE, REST_FRAMEWORK, SIMPLE_JWT, CACHES, LOGGING; nimoh_base_urlpatterns() one-liner URL registration; make_celery() factory |
| CLI | nimoh-base init — interactive project scaffolding; nimoh-base check — settings validation; nimoh-base config-template — dump a ready-to-edit NIMOH_BASE snippet |
Requirements
| Dependency | Version |
|---|---|
| Python | ≥ 3.12 |
| Django | ≥ 5.1, < 6.0 |
| djangorestframework | ≥ 3.15 |
| djangorestframework-simplejwt | ≥ 5.3 |
| Redis | any recent version (caching + Celery broker) |
| PostgreSQL | recommended (any Django-supported DB works for basic usage) |
Installation
From PyPI
pip install nimoh-be-django-base
From GitHub (SSH — for private repos / latest main)
pip install "git+ssh://git@github.com/ThriledLokki983/nimoh-be-django-base.git"
Editable install (local development)
git clone git@github.com:ThriledLokki983/nimoh-be-django-base.git
pip install -e "nimoh-be-django-base[dev]"
Optional extras
pip install "nimoh-be-django-base[sendgrid]" # SendGrid email backend
pip install "nimoh-be-django-base[gis]" # PostGIS / GeoDjango support
pip install "nimoh-be-django-base[cli]" # Interactive CLI scaffolding
pip install "nimoh-be-django-base[all]" # Everything above
Quick Start
Step 1 — Add to INSTALLED_APPS
# config/settings/base.py
from nimoh_base.conf import NimohBaseSettings
INSTALLED_APPS = NimohBaseSettings.get_base_apps() + [
"myproject.profiles",
"myproject.myapp",
]
get_base_apps() returns the four package apps in dependency order
(nimoh_core, nimoh_auth, nimoh_monitoring, nimoh_privacy) plus all
required third-party apps (rest_framework, corsheaders, drf_spectacular, …).
Step 2 — Configure NIMOH_BASE
NIMOH_BASE = {
# ── Required ──────────────────────────────────────────────────
"SITE_NAME": "My Application",
"SUPPORT_EMAIL": "support@myapp.com",
"NOREPLY_EMAIL": "noreply@myapp.com",
# ── Optional (shown with defaults) ────────────────────────────
"SERVER_HEADER": "", # omit HTTP Server header if empty
"PASSWORD_CHECKER_USER_AGENT": "Django-Password-Validator",
"CELERY_APP_NAME": "django-app",
"CACHE_KEY_PREFIX": "app",
"MOBILE_APP_IDENTIFIERS": [], # e.g. ["my-ios", "my-android"]
"ENABLE_MONITORING_PERSISTENCE": False, # write metrics to DB
}
See docs/SETTINGS.md for the full reference.
Step 3 — Middleware, REST framework, auth model
MIDDLEWARE = NimohBaseSettings.get_base_middleware()
REST_FRAMEWORK = NimohBaseSettings.get_base_rest_framework()
# Must subclass AbstractNimohUser — see "Extending the User Model" section
AUTH_USER_MODEL = "profiles.User"
Step 4 — URL patterns
# config/urls.py
from django.contrib import admin
from django.urls import path
from nimoh_base.conf.urls import nimoh_base_urlpatterns
urlpatterns = [
path("admin/", admin.site.urls),
*nimoh_base_urlpatterns(api_prefix="api/v1/"),
# …your project-specific routes
]
Step 5 — Migrate
python manage.py migrate
CLI — nimoh-base
Install the [cli] extra then run:
# Scaffold a new project interactively (creates settings, urls, celery, user model)
nimoh-base init
# Validate that all required NIMOH_BASE keys are present and correctly typed
nimoh-base check
# Print a ready-to-copy NIMOH_BASE config block
nimoh-base config-template
nimoh-base init walkthrough
$ nimoh-base init
? Project name: My Cool App
? Support email: support@mycoolapp.com
? No-reply email: noreply@mycoolapp.com
? Enable PostGIS / geo support? No
? Enable monitoring DB persistence? No
✅ Creating project: my-cool-app
config/settings/base.py written
config/settings/development.py written
config/urls.py written
myapp/celery.py written
profiles/models.py written (User stub)
requirements.txt written
Extending the User Model
Always subclass AbstractNimohUser, even if you add zero extra fields.
This keeps Django's auth swappable machinery intact.
# profiles/models.py
from nimoh_base.auth.models import AbstractNimohUser
from django.db import models
class User(AbstractNimohUser):
'''Project-specific user model — add custom fields here.'''
bio = models.TextField(blank=True)
avatar_url = models.URLField(blank=True)
class Meta(AbstractNimohUser.Meta):
swappable = "AUTH_USER_MODEL"
AbstractNimohUser built-in fields
| Field | Type | Notes |
|---|---|---|
email |
EmailField(unique=True) |
USERNAME_FIELD |
username |
CharField(max_length=150) |
in REQUIRED_FIELDS |
email_verified |
BooleanField(default=False) |
set by email-verify flow |
email_verified_at |
DateTimeField(null=True) |
timestamp of first verify |
failed_login_attempts |
PositiveIntegerField(default=0) |
incremented on auth failure |
locked_until |
DateTimeField(null=True) |
cleared by unlock_account() |
Account-lock helpers
user.is_account_locked() # → bool
user.lock_account(duration_minutes=30) # sets locked_until
user.unlock_account() # clears the lock
user.record_failed_login() # increments counter; may auto-lock
user.record_successful_login() # resets counter
Important: set
AUTH_USER_MODELin settings before running the firstmigrate. Changing it afterwards requires a database rebuild.
See docs/EXTENDING.md for advanced patterns.
URL Reference
nimoh_base_urlpatterns() mounts the following routes under <api_prefix>:
| Mount path | App | Description |
|---|---|---|
auth/ |
nimoh_auth |
Registration, login, refresh, logout, email verify, password reset, MFA, device sessions |
monitoring/ |
nimoh_monitoring |
Performance metrics, health-check aggregates |
privacy/ |
nimoh_privacy |
GDPR profile, consent, data-processing log, data export |
health/ |
nimoh_core |
Liveness (/health/) and readiness (/health/ready/) probes |
schema/ |
drf-spectacular | OpenAPI schema download |
schema/ui/ |
drf-spectacular | Swagger UI |
# Selective registration — disable what you don't need
urlpatterns = [
*nimoh_base_urlpatterns(
api_prefix="api/v1/",
include_auth=True,
include_monitoring=False, # opt-out monitoring routes
include_privacy=True,
include_schema=True,
include_health=True,
),
]
Celery Setup
# myproject/celery.py
import os
from nimoh_base.conf.celery import make_celery
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.development")
app = make_celery() # reads NIMOH_BASE['CELERY_APP_NAME'] for the Celery app name
# config/__init__.py
from .celery import app as celery_app
__all__ = ("celery_app",)
The Celery app is configured automatically from Django settings — no extra
app.config_from_object() call needed.
Email Template Overrides
The package ships base templates under:
nimoh_base/templates/emails/auth/— verification, password-reset, account-locknimoh_base/templates/emails/privacy/— GDPR export, data-deletion confirmation
Override any template by placing a file at the same relative path inside your project's template directory:
myproject/
└── templates/
└── emails/
└── auth/
└── email_verification_email.html ← overrides the package default
Django's template loader checks TEMPLATES[*]['DIRS'] before installed-app
templates — no custom loader, no monkey-patching required.
Configuration Reference
Full annotated reference: docs/SETTINGS.md
| Key | Required | Default | Description |
|---|---|---|---|
SITE_NAME |
✅ | — | Application display name; injected into all outbound emails |
SUPPORT_EMAIL |
✅ | — | Support address embedded in auth and GDPR emails |
NOREPLY_EMAIL |
✅ | — | From: address for all system emails |
SERVER_HEADER |
❌ | '' |
Value for HTTP Server response header; header omitted if empty |
PASSWORD_CHECKER_USER_AGENT |
❌ | 'Django-Password-Validator' |
User-Agent sent to the HIBP Pwned Passwords API |
CELERY_APP_NAME |
❌ | 'django-app' |
Name passed to Celery(name) constructor |
CACHE_KEY_PREFIX |
❌ | 'app' |
Prefix for all Redis cache keys |
MOBILE_APP_IDENTIFIERS |
❌ | [] |
Extra User-Agent substrings treated as mobile clients |
ENABLE_MONITORING_PERSISTENCE |
❌ | False |
When True, HTTP/DB metrics are written to nimoh_monitoring tables |
Architecture Decisions
D1 — Single NIMOH_BASE dict over many discrete settings
All package config lives under one key. Consumer projects can diff/grep/override
the full package surface at a glance, and nimoh_base.conf validates it at
AppConfig.ready() with a clear ImproperlyConfigured error if required keys are absent.
D2 — AbstractNimohUser over a concrete swappable model
Consumers must supply their own concrete User subclass (even an empty one).
This keeps AUTH_USER_MODEL flexible and removes the traditional "I can't add
fields because the package owns the model" friction.
D3 — Prefixed app labels (nimoh_auth, nimoh_core, …)
Avoids silent collisions with common generic names (core, authentication)
that many consumer projects already use. Migration history from older apps can be
redirected via MIGRATION_MODULES.
D4 — Django's native template-loader override for emails
No custom template backend. Override works via standard TEMPLATES['DIRS']
ordering — the same mental model every Django developer already has.
D5 — Optional extras for heavy dependencies
sendgrid, gis, and cli are opt-in. A project that only needs auth +
monitoring doesn't pull in PostGIS binaries or Click/Questionary.
Further Reading
| Document | Contents |
|---|---|
| docs/SETTINGS.md | Full NIMOH_BASE key reference with types, validation rules, and examples |
| docs/EXTENDING.md | Subclassing AbstractNimohUser, custom serializers/views, middleware extension |
| docs/MIGRATION_GUIDE.md | Step-by-step: vanilla Django project → nimoh-be-django-base consumer |
| CHANGELOG.md | Version history and breaking-change notes |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nimoh_be_django_base-0.1.6.tar.gz.
File metadata
- Download URL: nimoh_be_django_base-0.1.6.tar.gz
- Upload date:
- Size: 201.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea3f0e06ce6e1d86c8b2c5d12ade033e07993fd6bb3e122b724cdb99fb7e4b30
|
|
| MD5 |
9f81292c8a9727ab2763441dafbadfa1
|
|
| BLAKE2b-256 |
d8b12dd0421f0e611cd6264aa0055b61176e6dd9e603ba7e006456c8ad062828
|
Provenance
The following attestation bundles were made for nimoh_be_django_base-0.1.6.tar.gz:
Publisher:
publish.yml on Nimoh-Digital-Solutions/be-django-base
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nimoh_be_django_base-0.1.6.tar.gz -
Subject digest:
ea3f0e06ce6e1d86c8b2c5d12ade033e07993fd6bb3e122b724cdb99fb7e4b30 - Sigstore transparency entry: 973639441
- Sigstore integration time:
-
Permalink:
Nimoh-Digital-Solutions/be-django-base@5420093aec9681eeced357b3623ab2465e41ef76 -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/Nimoh-Digital-Solutions
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5420093aec9681eeced357b3623ab2465e41ef76 -
Trigger Event:
push
-
Statement type:
File details
Details for the file nimoh_be_django_base-0.1.6-py3-none-any.whl.
File metadata
- Download URL: nimoh_be_django_base-0.1.6-py3-none-any.whl
- Upload date:
- Size: 244.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
36db904599a55fe5b19cd5d18093bf4d6dadf1c6f14423a56e729d822022454a
|
|
| MD5 |
9a973ec0b9886c536cebe7e1c842a2e5
|
|
| BLAKE2b-256 |
73cc0a3a81d61b667d6e441003d77ccfe1c0b24aae2fb82541636900ebd7c443
|
Provenance
The following attestation bundles were made for nimoh_be_django_base-0.1.6-py3-none-any.whl:
Publisher:
publish.yml on Nimoh-Digital-Solutions/be-django-base
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nimoh_be_django_base-0.1.6-py3-none-any.whl -
Subject digest:
36db904599a55fe5b19cd5d18093bf4d6dadf1c6f14423a56e729d822022454a - Sigstore transparency entry: 973639445
- Sigstore integration time:
-
Permalink:
Nimoh-Digital-Solutions/be-django-base@5420093aec9681eeced357b3623ab2465e41ef76 -
Branch / Tag:
refs/tags/v0.1.6 - Owner: https://github.com/Nimoh-Digital-Solutions
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5420093aec9681eeced357b3623ab2465e41ef76 -
Trigger Event:
push
-
Statement type: