Skip to main content

django-boosted

Lightweight helpers to extend Django’s admin with extra views, custom forms, and the matching UI affordances (object tools, permissions, standard responses).

Features

  • @admin_boost_object_view decorator – fetches the target object, checks permissions, and builds the default context before rendering your template.
  • AdminBoostMixin – registers the custom URLs, protects them with admin_site.admin_view, and injects extra object-tool buttons into the change form.
  • AuditMixin – adds created_by, updated_by, created_at, updated_at with automatic user tracking via middleware.
  • Additional templates – a change form template that renders the injected buttons plus a simple “Hello” view as a teaching aid.

Installation

pip install django-boosted

Quick start

# app/admin.py
from django.contrib import admin
from django_boosted.mixins import AdminBoostMixin
from django_boosted.decorators import admin_boost_object_view
from .models import Client


class ClientAdmin(AdminBoostMixin, admin.ModelAdmin):
    boost_views = ["hello_view"]
    change_form_template = "admin_boost/change_form.html"

    @admin_boost_object_view(label="Say hello", template_name="admin_boost/hello.html")
    def hello_view(self, request, obj):
        return {"message": f"Hello {obj}!"}


admin.site.register(Client, ClientAdmin)

Include the provided templates in your TEMPLATES["DIRS"] (or copy them to customize).

Using forms with ForeignKey widgets

The decorator can automatically apply admin widgets (ForeignKeyRawIdWidget or AutocompleteSelect) to your form fields, using the same logic as ModelAdmin.change_view():

# app/admin.py
from django import forms
from django.contrib import admin, messages
from django.shortcuts import redirect
from django_boosted.mixins import AdminBoostMixin
from django_boosted.decorators import admin_boost_object_view
from .models import Company

class SyncFullGroupForm(forms.Form):
    group = forms.ModelChoiceField(queryset=Company.objects.all())
    option = forms.ChoiceField(
        label="sync method",
        choices=[("method1", "Method 1"), ("method2", "Method 2")],
    )

class CompanyAdmin(AdminBoostMixin, admin.ModelAdmin):
    boost_views = ["sync_full_group_view"]
    change_form_template = "admin_boost/change_form.html"

    @admin_boost_object_view(
        label="Sync Full Group",
        template_name="admin/sync_full_group.html",
        form=SyncFullGroupForm,
        raw_id_fields=["group"],  # Automatically applies ForeignKeyRawIdWidget
    )
    def sync_full_group_view(self, request, obj, form):
        if request.method == "POST" and form.is_valid():
            # Process form...
            group = form.cleaned_data["group"]
            option = form.cleaned_data["option"]
            # ... your logic ...
            self.message_user(request, "Sync completed", messages.SUCCESS)
            return redirect(obj.admin_change_url)
        return {}  # Return additional context if needed

The decorator handles:

  • Widget application (respects raw_id_fields and autocomplete_fields)
  • Form validation on POST
  • Adding the form to the template context
  • Backward compatibility (if your view doesn't accept a form parameter, it won't be passed)

Global admin views & index panel

Register object-less admin views that reuse the existing view generators (adminform, form, confirm, message, list, json, redirect) — you only write the useful code that returns a form or a context dict, no template needed. Registered views are listed in a "Boosted" box on the admin index page, right before "Recent actions".

# app/boosted_views.py  (or app/admin.py)
from django import forms
from django.contrib import messages
from django.urls import reverse
from django_boosted import admin_boost_global_view


class ResyncForm(forms.Form):
    mode = forms.ChoiceField(choices=[("fast", "Fast"), ("full", "Full")])


@admin_boost_global_view("adminform", "Resync all")
def resync_all(request, form=None):
    if form is not None:  # valid POST
        # ... global logic ...
        messages.success(request, "Resync started")
        return {"redirect_url": reverse("admin:index")}
    return {"form": ResyncForm()}

Discovery — the decorator runs only if its module is imported. django-boosted imports, at startup:

  • a conventional boosted_views.py module in each installed app (auto), and
  • every module listed in DJANGO_BOOSTED_VIEW_MODULES (for files outside an app).
# settings.py
DJANGO_BOOSTED_VIEW_MODULES = ["myproject.ops.boosted_views"]

Views defined in an app's admin.py also work, since Django already imports it.

Options: path_fragment, template_name, permission (a permission codename, a callable(request) -> bool, or None for any staff user), order, show_in_index. Use register_index_view(label, url, ...) to add a plain link (e.g. reverse_lazy(...) to an existing admin view).

adminform views render the standard admin change-form "Save" button. To rename it, return save_label in the context dict:

@admin_boost_global_view("adminform", "Resync all")
def resync_all(request, form=None):
    if form is not None:
        return {"redirect_url": reverse("admin:index")}
    return {"form": ResyncForm(), "save_label": "Run resync"}

To render fields as Django admin readonly (plain text, not an input), return readonly_fields. Works with a regular Form or a ModelForm. Include the key on every return that still shows the form:

@admin_boost_global_view("adminform", "Generate token")
def generate_token(request, form=None):
    if form is not None:
        return {
            "form": ResultForm(initial={"token": token, "url": url}),
            "readonly_fields": ["token", "url"],
        }
    return {"form": GenerateForm(), "readonly_fields": ["token", "url"]}

For several buttons (with a color class each), return save_buttons; inspect request.POST to know which one was pressed. Available classes: default, success, info, warning, danger, primary, secondary.

@admin_boost_global_view("adminform", "Resync all")
def resync_all(request, form=None):
    if form is not None:
        if "_full" in request.POST:
            ...  # full resync
        return {"redirect_url": reverse("admin:index")}
    return {
        "form": ResyncForm(),
        "save_buttons": [
            {"name": "_fast", "label": "Fast", "class": "success"},
            {"name": "_full", "label": "Full", "class": "danger"},
        ],
    }

The box is wired via admin.site.index_template. If you use a custom AdminSite, set index_template = "admin_boost/index.html" on it.

Audit (created_by / updated_by)

  1. Add CurrentUserMiddleware to MIDDLEWARE (after AuthenticationMiddleware):
MIDDLEWARE = [
    ...
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    ...
    "django_boosted.middleware.CurrentUserMiddleware",
]
  1. Use AuditMixin on your models:
from django.db import models
from django_boosted import AuditMixin

class Article(AuditMixin, models.Model):
    title = models.CharField(max_length=200)

The mixin automatically sets created_by on first save and updated_by on each save when a user is authenticated.

created_by and updated_by use AuditUserField: auto-filled with configurable concatenation. Default: ('pk', 'username') joined with _. Override audit_user_format and audit_user_separator on the model, or use the field directly:

# Via mixin
class Article(AuditMixin, models.Model):
    audit_user_format = ("pk", "email")
    audit_user_separator = "-"

# Or use AuditUserField standalone
from django_boosted import AuditUserField

class Log(models.Model):
    editor = AuditUserField(format_fields=("pk", "username"), mode="updated")

Settings:

  • DJANGO_BOOSTED_AUDIT_USER_FALLBACK — default value when no request user (migrations, commands, scripts). Example: "robot_octolo". If not set, default is None.
  • DJANGO_BOOSTED_AUDIT_USER_FORMAT_FIELDS — tuple of user attributes for the stored value. Default: ("pk", "username").
  • DJANGO_BOOSTED_AUDIT_USER_SEPARATOR — separator between format fields. Default: "_".

In templates or Python, created_by and updated_by return AuditUserValue (str subclass) with admin_url:

obj.created_by  # "42-johndoe"
obj.created_by.admin_url  # "/admin/auth/user/42/change/"

Development commands

Run everything via ./service.py dev <command> or python dev.py <command>:

Command Description
./service.py dev install-dev or python dev.py install-dev create the venv and install the package editable with dev extras.
./service.py dev lint or python dev.py lint run Ruff + Black in check mode.
./service.py dev format or python dev.py format apply Ruff --fix then Black.
./service.py dev test or python dev.py test run pytest (with pytest-django).
./service.py dev build or python dev.py build clean then build wheel + sdist.
./service.py quality security or python dev.py security Bandit + Safety + pip-audit.
./service.py dev help or python dev.py help list all commands.

License

MIT — see the LICENSE file. Contributions welcome!

Metadata

Release files for django-boosted 1.0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-boosted 1.0.4
File Size Uploaded Provenance
django_boosted-1.0.4.tar.gz 33.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-boosted 1.0.4
File Interpreter ABI Platform
django_boosted-1.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 78.0 kB

Release files / django_boosted-1.0.4.tar.gz

Download URL django_boosted-1.0.4.tar.gz
Size 33.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a2a8a9f0e051554803daddbe0591d3ff96d1dec41d0547ab431f40b3440a2d81
BLAKE2b-256 checksum
How to use checksums
ba76d5aa1d195fa0961f24aeb3e56af337e28f6b524abb132da5b670a158890e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Release files / django_boosted-1.0.4-py3-none-any.whl

Download URL django_boosted-1.0.4-py3-none-any.whl
Size 44.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d66d3d41cbcaac57a92e3b8d95706ea3e0e442afcda90dc2e4fa0e80971f9ee9
BLAKE2b-256 checksum
How to use checksums
8c36c1161099ac0f076d71c3dd69ba99b221b4ca7ca55f9dd8b592d58806077b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

Security for django-boosted 1.0.4

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for django_boosted-1.0.4.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 15, 2026.

Transparency log

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page