DjSuperAdmin
✍️ Edit contents directly on your page with Django
Here's how it works
Superusers get an inline editor (SunEditor, lazy-loaded from a CDN on first edit) right on the rendered page. Everyone else just sees the plain content.
Compatibility
- Django 2.0 → latest (tested 2.2 → 6.0)
- Python 3.6+
- Zero runtime dependencies (other than Django itself)
Installation
pip install djsuperadmin
# or
uv add djsuperadmin
Setup
Add the app to INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"djsuperadmin",
]
Include the urls only if you use the built-in Content model (i.e. the bare-string
tag form shown below):
from django.urls import path, include
urlpatterns = [
# ...
path("", include("djsuperadmin.urls")),
]
Finally, load the template tags and drop {% djsuperadminjs %} once in your footer.
It injects the djsuperadmin bundle (which lazy-loads SunEditor on first edit), and
renders only for authenticated superusers (empty string for everyone else):
{% load djsuperadmintag %}
<!-- ... your page ... -->
{% djsuperadminjs %}
Usage
Simple (bare string)
Pass a default string. djsuperadmin stores it in its built-in Content model, keyed by a
hash of the text and auto-created on first render. Requires the urls to be included.
{% load djsuperadmintag %}
{% superadmin_content 'Some default text' %}
Raw content
Same as above but with a plain textarea editor (no WYSIWYG) — good for plain text or
snippets. Note the tag name is superadmin_raw_content:
{% superadmin_raw_content 'Some default text' %}
Bind to a model attribute
Both tags also accept an object and an attribute name. Superusers see an editable
element (a <div class="djsuperadmin"> for WYSIWYG, a <span> for raw), everyone
else sees the plain value:
{% superadmin_content my_object 'body' %}
{% superadmin_raw_content my_object 'body' %}
Advanced: your own content model + endpoint
Mix in DjSuperAdminMixin and expose a GET/PATCH endpoint. The mixin raises
NotImplementedError if the two url properties are not defined.
from django.db import models
from djsuperadmin.mixins import DjSuperAdminMixin
class MyContent(models.Model, DjSuperAdminMixin):
body = models.TextField()
@property
def superadmin_get_url(self):
return f"/api/mycontent/{self.pk}"
@property
def superadmin_patch_url(self):
return f"/api/mycontent/{self.pk}"
Your endpoint must:
GET→ return JSON{"content": <value>}PATCHwith body{"content": <value>}→ save it
Then render it like any other object:
{% superadmin_content my_content 'body' %}
Settings
DJSUPERADMIN = {"INPLACE_EDIT": True}
When INPLACE_EDIT is True, contents are edited right on the page instead of in a
modal: raw contents via contenteditable, and WYSIWYG contents via an inline SunEditor
(its toolbar docks above the content while editing; click the toolbar's save button to
commit, or press Esc to cancel). Defaults to False (modal editing).
Version history / revert
Every save keeps the previous value. Hovering an editable content shows a toolbar
(✏️ edit + ⟲ history); the history icon lists past versions (timestamp + preview)
and clicking one restores it — reverting is itself an undoable save. Works out of the box for the built-in Content model (capped by
MAX_VERSIONS, default 20). Your own models opt in by exposing a
superadmin_history_url — see the docs.
DJSUPERADMIN = {"INPLACE_EDIT": True, "MAX_VERSIONS": 20}
Insert images from a media gallery
Point IMAGE_GALLERY_URL at an endpoint that returns
{"result": [{"src": "...", "name": "..."}, ...]} and the WYSIWYG toolbar gains an
"insert image from gallery" button. This is designed to plug into a CMS media
library. IMAGE_UPLOAD_URL (optional) enables direct uploads.
DJSUPERADMIN = {
"INPLACE_EDIT": True,
"IMAGE_GALLERY_URL": "/api/media/", # returns the media list as JSON
}
The WYSIWYG editor (SunEditor) is lazy-loaded from jsDelivr. To self-host it — e.g. under a strict Content-Security-Policy — override the URLs:
DJSUPERADMIN = {
"SUNEDITOR_JS": "/static/vendor/suneditor.min.js",
"SUNEDITOR_CSS": "/static/vendor/suneditor.min.css",
}
Development
Contributions welcome — see CONTRIBUTING.md. Tooling is uv (Python) + pnpm (JS build & docs), with the frontend bundle built by Vite.
make install # uv sync --dev && pnpm install
make test # flake8 + pytest with coverage
make format # black .
make lint # flake8 djsuperadmin
make build # rebuild djsuperadmin/static/djsuperadmin/djsuperadmin.bundle.js
make migrations # uv run python manage.py makemigrations
make docs-dev # VitePress docs (also: docs-build, docs-preview)
Run the demo / test project (example/, settings module
example.djsuperadmin_example.settings):
uv run python manage.py migrate
uv run python manage.py createsuperuser
uv run python manage.py runserver # log in at /admin/, then open /
Documentation
Full docs: https://bnznamco.github.io/djsuperadmin/
Metadata
Release files for djsuperadmin 1.0.1
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 | |
|---|---|---|---|---|
| djsuperadmin-1.0.1.tar.gz | 18.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| djsuperadmin-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.9 kB
Release files / djsuperadmin-1.0.1.tar.gz
| Download URL | djsuperadmin-1.0.1.tar.gz |
|---|---|
| Size | 18.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
289c24a11bf1148e6e12f75d076ec4133741813e68c742c12907d5a3b54eed72
|
|
BLAKE2b-256 checksum How to use checksums |
293060868833f07bb5476200012be6287c3eb36ff98fa7abdfd6e71c2ff0d039
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / djsuperadmin-1.0.1-py3-none-any.whl
| Download URL | djsuperadmin-1.0.1-py3-none-any.whl |
|---|---|
| Size | 16.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ac16a5947fc5f5150c04b2261057fee3a0ce0da0b16181d3e571c6ca06da986a
|
|
BLAKE2b-256 checksum How to use checksums |
ac116949827a5b1b80fec3dbb42a88a15d523a63ee51407d064923fa92f310df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Security for djsuperadmin 1.0.1
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.