Skip to main content

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

  1. Features
  2. Requirements
  3. Installation
  4. Quick Start
  5. CLI — nimoh-base
  6. Extending the User Model
  7. URL Reference
  8. Celery Setup
  9. Email Template Overrides
  10. Configuration Reference
  11. Architecture Decisions
  12. Further Reading
  13. 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_MODEL in settings before running the first migrate. 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-lock
  • nimoh_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/GETTING_STARTED.md Scaffold a new project from scratch; first-run setup
docs/DEVELOPMENT_GUIDE.md Day-to-day development: models, views, tasks, tests, logging
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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nimoh_be_django_base-0.2.7.tar.gz (231.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nimoh_be_django_base-0.2.7-py3-none-any.whl (258.4 kB view details)

Uploaded Python 3

File details

Details for the file nimoh_be_django_base-0.2.7.tar.gz.

File metadata

  • Download URL: nimoh_be_django_base-0.2.7.tar.gz
  • Upload date:
  • Size: 231.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nimoh_be_django_base-0.2.7.tar.gz
Algorithm Hash digest
SHA256 2293aeedab5d94773370a74025e4be9b71c769f19d21bc21d7a5c7aa99d46eba
MD5 c975278e79792d1b36ef1257cfc326d1
BLAKE2b-256 eecf64bfa56535be29640b6cb736fb16a0cacc5e74a40e33c759077d4422198e

See more details on using hashes here.

Provenance

The following attestation bundles were made for nimoh_be_django_base-0.2.7.tar.gz:

Publisher: publish.yml on Nimoh-Digital-Solutions/be-django-base

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nimoh_be_django_base-0.2.7-py3-none-any.whl.

File metadata

File hashes

Hashes for nimoh_be_django_base-0.2.7-py3-none-any.whl
Algorithm Hash digest
SHA256 5403a8b64cda4c41928dd5f584a5d030b6d74ada828f0f9398a0f79305007aee
MD5 ab3db2353a39d3f0b93864b8722ea299
BLAKE2b-256 839ea14574f8b8699d87ae7494f36c980b434671f3d2d7959cd18e03af65c197

See more details on using hashes here.

Provenance

The following attestation bundles were made for nimoh_be_django_base-0.2.7-py3-none-any.whl:

Publisher: publish.yml on Nimoh-Digital-Solutions/be-django-base

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page