Edit contents directly on your page with Django
Project description
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/
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 djsuperadmin-1.0.1.tar.gz.
File metadata
- Download URL: djsuperadmin-1.0.1.tar.gz
- Upload date:
- Size: 18.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
289c24a11bf1148e6e12f75d076ec4133741813e68c742c12907d5a3b54eed72
|
|
| MD5 |
914e91ed99e22c3fe52ca9caf96ac845
|
|
| BLAKE2b-256 |
293060868833f07bb5476200012be6287c3eb36ff98fa7abdfd6e71c2ff0d039
|
File details
Details for the file djsuperadmin-1.0.1-py3-none-any.whl.
File metadata
- Download URL: djsuperadmin-1.0.1-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac16a5947fc5f5150c04b2261057fee3a0ce0da0b16181d3e571c6ca06da986a
|
|
| MD5 |
c5da0b97a95bf8847dbc6bfb7d0cc401
|
|
| BLAKE2b-256 |
ac116949827a5b1b80fec3dbb42a88a15d523a63ee51407d064923fa92f310df
|