Django Accounts Framework FDG
A reusable Django authentication and role-management application built with Django REST Framework. It provides email-based accounts, session authentication, activation and password recovery, a custom user model with public UUIDs, user administration, and Django Group-based roles.
Release status:
0.1.0is an initial packaging candidate. Test it in a fresh Django project before publishing or using it in production. This package provides its own user model and is intended primarily for new Django projects.
Features
- Email-based registration, sign-in, sign-out, account activation, and password reset.
- User profile and administrative account APIs.
- A custom
accounts.Usermodel with a random, uniquepublic_idUUID for public API references. - Forced-password-change middleware with configurable protected paths and exemptions.
- Django Groups, multiple roles per user, permission checks, and a Django Admin Role Setup Wizard.
- Configurable project branding, frontend links, activation behavior, and email templates.
- Django system checks for important configuration requirements.
Security boundary: UUIDs are opaque identifiers, not authorization. Each project must still enforce authentication, permissions, and object ownership. The Accounts app does not replace a project's CORS, CSRF, HTTPS, or session-cookie configuration.
Requirements and installation
The package metadata currently declares Python 3.13+, Django 6.x, and Django REST Framework 3.16+. These are declared compatibility ranges, not a claim that all combinations have been independently tested.
To install a local editable copy from the package repository:
python -m pip install -e .
After building a wheel with python -m build, you can also install that wheel into a fresh virtual environment to validate the packaged distribution:
python -m pip install path/to/django_accounts_framework_fdg-0.1.0-py3-none-any.whl
After publication on PyPI, installation would use:
python -m pip install django-accounts-framework-fdg
This last command applies only after the distribution has actually been published.
Import-name note: The installed distribution is named
django-accounts-framework-fdg, but the Django application is imported asaccounts. Avoid installing another package that uses the same top-level Python module name.
Configure a new Django project
1. Install and configure the custom User model
In your project's settings.py, add the app and set the custom user model before running initial migrations:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"accounts.apps.AccountsConfig",
]
AUTH_USER_MODEL = "accounts.User"
If your project already has users and migrations using a different user model, switching to accounts.User is not a drop-in operation. Plan a dedicated data and schema migration instead.
2. Configure middleware
Keep your project's normal Django security, session, CSRF, authentication, and message middleware. Place the Accounts middleware after AuthenticationMiddleware:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"accounts.force_password_middleware.ForcePasswordChangeMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
3. Mount Accounts URLs
In the host project's urls.py:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include("accounts.urls")),
]
The /api/ mount point is only an example. Accounts' own routes use auth/… and a permissions/ endpoint relative to wherever you mount them. Named URLs let the forced-password middleware identify its essential account exemptions even when the mount point changes. Ensure your frontend calls the corresponding paths.
4. Configure branding and account behavior
Add an application-specific ACCOUNTS_FRAMEWORK dictionary to settings.py:
ACCOUNTS_FRAMEWORK = {
"SITE_NAME": "Example Application",
"FRONTEND_URL": "https://app.example.com",
"SITE_URL": "https://api.example.com/",
"LOGO_URL": "https://example.com/static/logo.png",
"SUPPORT_EMAIL": "support@example.com",
"BRAND_COLOR": "#0F766E",
"ENABLE_SELF_REGISTRATION": True,
"REQUIRE_EMAIL_ACTIVATION": True,
"ACTIVATION_PATH": "/activate-account",
"PASSWORD_RESET_PATH": "/reset-password",
"ACTIVATION_TOKEN_EXPIRY_HOURS": 24,
"PASSWORD_RESET_EXPIRY_HOURS": 2,
"SEND_WELCOME_EMAIL": False,
"ROLE_PRESETS": [], # Define the new project's groups/permissions.
"MANAGER_ASSIGNABLE_ROLES": [],
}
Set up a working Django email backend and sender identity in the host project. Ensure activation and reset paths exist in your frontend. Never commit SMTP credentials, database passwords, or Django secret keys.
5. Run initial setup
With your database configured, run:
python manage.py check
python manage.py migrate
python manage.py createsuperuser
Sign in to Django Admin and open the Role Setup Wizard to create your configured Groups. Business apps should define their own permissions and use user.has_perm("app_label.codename"); keep those domain-specific permission definitions outside Accounts.
Forced password changes: protected paths versus allowed paths
When a signed-in user has must_change_password=True, ForcePasswordChangeMiddleware restricts access until their password is changed. Two settings let each project control the scope:
| Setting | Default | Purpose |
|---|---|---|
ACCOUNTS_FORCE_PASSWORD_PROTECTED_PREFIXES |
("/",) |
Where to enforce the password-change restriction. The default covers the whole website. |
ACCOUNTS_FORCE_PASSWORD_ALLOWED_PREFIXES |
() |
Exceptions that the user may still reach before changing their password. |
For example, a project might enforce the rule for API routes while allowing a token-based public download endpoint:
ACCOUNTS_FORCE_PASSWORD_PROTECTED_PREFIXES = (
"/api/",
)
ACCOUNTS_FORCE_PASSWORD_ALLOWED_PREFIXES = (
"/api/public-downloads/",
)
With must_change_password=True:
| Example request | Middleware behavior |
|---|---|
/api/private-data/ |
Blocked with HTTP 403 |
/api/public-downloads/file-token/ |
Permitted past this middleware |
/api/auth/change-password/ |
Permitted by Accounts' built-in account-route exception |
/dashboard/ |
Outside the configured protected scope |
Important: Allowed paths do not clear must_change_password; they only bypass this middleware check. Views must still enforce their own authentication, token validation, and permissions. Keep prefix exemptions narrow, because a prefix also exempts all paths underneath it. Necessary built-in account endpoints and static assets are also exempted so users can complete the password-change flow.
Public identifiers and account administration
accounts.User.public_idis the UUID intended for public account identifiers; internal integer database primary keys remain an implementation detail.- Administration endpoints that target users accept
user_public_idrather than exposing a database ID. - Django Groups and permissions are referenced by Group name and permission code (
app_label.codename), not public numeric IDs. - A non-superuser holding
accounts.manage_usersmay assign only Groups listed inMANAGER_ASSIGNABLE_ROLES. Keep this allowlist limited to low-privilege roles; theAdministratorrole is superuser-only to assign.
Representative routes when mounted under /api/:
| Endpoint | Purpose |
|---|---|
/api/auth/csrf/ |
Obtain CSRF cookie/token support |
/api/auth/register/ |
Register account |
/api/auth/activate/ |
Activate account |
/api/auth/login/, /api/auth/logout/ |
Session authentication |
/api/auth/me/ |
Current user/profile |
/api/auth/change-password/ |
Change password |
/api/auth/password-reset/request/ |
Start password reset |
/api/auth/password-reset/check/ |
Validate reset flow |
/api/auth/password-reset/confirm/ |
Complete reset |
/api/auth/roles/, /api/auth/assign-role/ |
Roles and assignments |
/api/auth/set-active/ |
User active status |
/api/auth/admin-set-password/ |
Administrative password action |
See accounts/urls.py and the corresponding serializers/views for supported methods, request payloads, and permission requirements.
Email templates
The package includes text and HTML templates under:
accounts/templates/accounts/emails/
├── activation_email.html
├── activation_email.txt
├── password_reset_email.html
├── password_reset_email.txt
├── welcome_email.html
└── welcome_email.txt
Confirm these templates are present in the built wheel. The containing Django project must enable app template loading (APP_DIRS=True) or configure equivalent template loaders.
Testing and release preparation
In a newly created Django integration project (with no business-specific apps installed), run:
python manage.py check
python manage.py makemigrations --check --dry-run
python manage.py migrate
python manage.py test accounts
Test registration, session login, activation and password recovery, CSRF/cookies, forced password changes, administrative permissions, and the Role Setup Wizard. Validate against each database engine and Python/Django version you intend to support.
To build and validate the distribution from this repository:
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/*
unzip -l dist/*.whl
Verify that the wheel includes accounts/migrations/ and email templates, and that the metadata contains this README as its long description. Passing package checks does not replace clean-install integration tests.
Scope and compatibility notes
- This package ships a concrete custom User model. Adopt it at project initialization, not as an unplanned replacement for an established user schema.
- The account API's JSON shapes and internal route names are part of its public integration contract.
- The package does not host your frontend, configure SMTP credentials, or automatically manage allowed cross-origin browser requests.
- Its current distribution name and version are proposed release values; confirm availability and legal/licensing choices before publishing publicly.
License
This project is licensed under the MIT License. See the LICENSE file for the full license text.
Metadata
Release files for django-accounts-framework-fdg 0.1.0
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 |
|---|---|---|---|---|
| django_accounts_framework_fdg-0.1.0.tar.gz | 36.6 kB | Without provenance | Details for django_accounts_framework_fdg-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_accounts_framework_fdg-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for django_accounts_framework_fdg-0.1.0-py3-none-any.whl |
Total release size: 79.3 kB
Release files / django_accounts_framework_fdg-0.1.0.tar.gz
| Download URL | django_accounts_framework_fdg-0.1.0.tar.gz |
|---|---|
| Size | 36.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
036630a1e34e6c21e3a517c9c38a7b14d2f9db62df9d14bf1d248d12dc73bf0e
|
|
BLAKE2b-256 checksum How to use checksums |
6b7c9a58a1c1ebd142053a3d5438de58c9173425ad4fe52f57d8f436738e8b7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / django_accounts_framework_fdg-0.1.0-py3-none-any.whl
| Download URL | django_accounts_framework_fdg-0.1.0-py3-none-any.whl |
|---|---|
| Size | 42.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c379b2220b7ad349aa0da00c0cb5380cbcf03d3e0e98eed1f870da5eb1ba277a
|
|
BLAKE2b-256 checksum How to use checksums |
aed18e04fd0b6c2592b7ad872aa6db4836560f88420b7adf54fcf297128683f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Security for django-accounts-framework-fdg 0.1.0
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.