django-admin-react 0.2.0a8__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/PKG-INFO +71 -40
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/README.md +67 -38
- django_admin_react-1.0.1/django_admin_react/__init__.py +25 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/audit.py +16 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/conf.py +26 -13
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/pwa.py +5 -1
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/static/admin_react/.vite/manifest.json +2 -2
- django_admin_react-1.0.1/django_admin_react/static/admin_react/assets/index-CDjd0bZa.js +8 -0
- django_admin_react-1.0.1/django_admin_react/static/admin_react/assets/index-Fn2O5Tqj.css +1 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/static/admin_react/index.html +2 -2
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/admin_react/index.html +7 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/urls.py +33 -11
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/views.py +41 -3
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/pyproject.toml +14 -2
- django_admin_react-0.2.0a8/django_admin_react/__init__.py +0 -10
- django_admin_react-0.2.0a8/django_admin_react/api/README.md +0 -31
- django_admin_react-0.2.0a8/django_admin_react/api/__init__.py +0 -5
- django_admin_react-0.2.0a8/django_admin_react/api/dates.py +0 -215
- django_admin_react-0.2.0a8/django_admin_react/api/filters.py +0 -412
- django_admin_react-0.2.0a8/django_admin_react/api/inlines.py +0 -358
- django_admin_react-0.2.0a8/django_admin_react/api/inlines_write.py +0 -241
- django_admin_react-0.2.0a8/django_admin_react/api/panels.py +0 -113
- django_admin_react-0.2.0a8/django_admin_react/api/permissions.py +0 -132
- django_admin_react-0.2.0a8/django_admin_react/api/registry.py +0 -399
- django_admin_react-0.2.0a8/django_admin_react/api/serializers.py +0 -467
- django_admin_react-0.2.0a8/django_admin_react/api/urls.py +0 -164
- django_admin_react-0.2.0a8/django_admin_react/api/views/README.md +0 -22
- django_admin_react-0.2.0a8/django_admin_react/api/views/__init__.py +0 -6
- django_admin_react-0.2.0a8/django_admin_react/api/views/actions.py +0 -196
- django_admin_react-0.2.0a8/django_admin_react/api/views/auth.py +0 -192
- django_admin_react-0.2.0a8/django_admin_react/api/views/autocomplete.py +0 -163
- django_admin_react-0.2.0a8/django_admin_react/api/views/bulk.py +0 -248
- django_admin_react-0.2.0a8/django_admin_react/api/views/create.py +0 -213
- django_admin_react-0.2.0a8/django_admin_react/api/views/create_form.py +0 -229
- django_admin_react-0.2.0a8/django_admin_react/api/views/delete_preview.py +0 -107
- django_admin_react-0.2.0a8/django_admin_react/api/views/destroy.py +0 -93
- django_admin_react-0.2.0a8/django_admin_react/api/views/detail.py +0 -482
- django_admin_react-0.2.0a8/django_admin_react/api/views/history.py +0 -166
- django_admin_react-0.2.0a8/django_admin_react/api/views/list.py +0 -493
- django_admin_react-0.2.0a8/django_admin_react/api/views/password.py +0 -161
- django_admin_react-0.2.0a8/django_admin_react/api/views/registry.py +0 -53
- django_admin_react-0.2.0a8/django_admin_react/api/views/schema.py +0 -494
- django_admin_react-0.2.0a8/django_admin_react/api/views/update.py +0 -220
- django_admin_react-0.2.0a8/django_admin_react/api/writes.py +0 -457
- django_admin_react-0.2.0a8/django_admin_react/static/admin_react/assets/index-BSzI7RU6.css +0 -1
- django_admin_react-0.2.0a8/django_admin_react/static/admin_react/assets/index-CxlHfz-w.js +0 -8
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/LICENSE +0 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/README.md +0 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/apps.py +0 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/README.md +0 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/admin_react/README.md +0 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/admin_react/login.html +0 -0
- {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/admin_react/sw.js +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: django-admin-react
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: A drop-in React single-page admin for Django, driven entirely by ModelAdmin.
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: django,admin,react,spa,tailwind
|
|
7
7
|
Author: django-admin-react contributors
|
|
8
8
|
Requires-Python: >=3.10,<4.0
|
|
9
|
-
Classifier: Development Status ::
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
10
|
Classifier: Environment :: Web Environment
|
|
11
11
|
Classifier: Framework :: Django
|
|
12
12
|
Classifier: Framework :: Django :: 5.0
|
|
@@ -24,6 +24,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
24
24
|
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
|
|
25
25
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
26
|
Requires-Dist: django (>=5.0,<7.0)
|
|
27
|
+
Requires-Dist: django-admin-mcp-api (>=0.1.0a0,<0.2.0)
|
|
28
|
+
Requires-Dist: django-admin-rest-api (>=1.0.1,<2.0.0)
|
|
27
29
|
Project-URL: Documentation, https://github.com/MartinCastroAlvarez/django-admin-react#readme
|
|
28
30
|
Project-URL: Homepage, https://github.com/MartinCastroAlvarez/django-admin-react
|
|
29
31
|
Project-URL: Repository, https://github.com/MartinCastroAlvarez/django-admin-react
|
|
@@ -35,11 +37,43 @@ A drop-in **React single-page admin** for any Django 5+ project. Same
|
|
|
35
37
|
`pip install`, same `INSTALLED_APPS`, same `urls.py include()` — and
|
|
36
38
|
your `ModelAdmin` classes drive everything. No React code on your side.
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
```python
|
|
41
|
+
# settings.py
|
|
42
|
+
INSTALLED_APPS = [
|
|
43
|
+
# ...
|
|
44
|
+
"django.contrib.admin",
|
|
45
|
+
"django_admin_react", # the React SPA — includes the JSON API for you
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
# urls.py
|
|
49
|
+
urlpatterns = [
|
|
50
|
+
path("admin/", admin.site.urls),
|
|
51
|
+
path("admin-react/", include("django_admin_react.urls")), # SPA + API in one include
|
|
52
|
+
]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**One `INSTALLED_APPS` line + one URL include is the entire integration.** `pip install django-admin-react` transitively pulls in the [JSON API](https://pypi.org/project/django-admin-rest-api/) and the [MCP adapter](https://pypi.org/project/django-admin-mcp-api/); `django_admin_react.urls` includes the API endpoints at `<mount>/api/v1/…`, so the SPA finds its wire surface with zero configuration. (Mount the API a second time at your own prefix only if a non-SPA client also needs it.)
|
|
56
|
+
|
|
57
|
+
> **Beta — v1.0.0.** Available on PyPI; the SPA + the API
|
|
58
|
+
> ([`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/))
|
|
59
|
+
> + the MCP adapter
|
|
60
|
+
> ([`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/))
|
|
61
|
+
> all share the v1 wire contract. Track progress on the
|
|
40
62
|
> [Project board](https://github.com/users/MartinCastroAlvarez/projects/3)
|
|
41
63
|
> and the [Issues list](https://github.com/MartinCastroAlvarez/django-admin-react/issues).
|
|
42
64
|
|
|
65
|
+
## Three repos, one product
|
|
66
|
+
|
|
67
|
+
The project is split into three independently-published, cross-referenced repos so each piece can be consumed on its own merits:
|
|
68
|
+
|
|
69
|
+
| Repo | PyPI | Role |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| **[`django-admin-rest-api`](https://github.com/MartinCastroAlvarez/django-admin-api)** | [`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/) | The JSON REST API for the Django admin — same permissions, same `ModelAdmin`, no new features. The wire surface. |
|
|
72
|
+
| **`django-admin-react`** *(this repo)* | [`django-admin-react`](https://pypi.org/project/django-admin-react/) | The React SPA frontend. A **super-layer** that depends on `django-admin-rest-api` for every wire call. |
|
|
73
|
+
| **[`django-admin-mcp-api`](https://github.com/MartinCastroAlvarez/django-admin-mcp)** | [`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/) | Wire-protocol-only **MCP** adapter (call, manifest, …) over `django-admin-rest-api` — lets agents reach the same `ModelAdmin`-driven REST surface, no new functionality / permissions / validation. |
|
|
74
|
+
|
|
75
|
+
The wire contract itself lives in the **API repo** (`docs/api-contract.md` there). This README is about the SPA. The migration from "self-contained" to the 3-repo split is tracked in [META #544](https://github.com/MartinCastroAlvarez/django-admin-react/issues/544).
|
|
76
|
+
|
|
43
77
|
---
|
|
44
78
|
|
|
45
79
|
## Why django-admin-react
|
|
@@ -77,8 +111,8 @@ permissions at runtime from `GET /api/v1/registry/`. Add a new
|
|
|
77
111
|
|
|
78
112
|
Real captures of the **django-admin-react SPA** rendering the bundled
|
|
79
113
|
`examples/` apps — driven entirely by each app's `ModelAdmin`.
|
|
80
|
-
|
|
81
|
-
|
|
114
|
+
Captured **manually** against a local dev server (no Playwright / Cypress /
|
|
115
|
+
e2e tooling required).
|
|
82
116
|
|
|
83
117
|
| Sign in (package login) | Registry / home |
|
|
84
118
|
| -------------------------------------------------- | ----------------------------------------------------- |
|
|
@@ -103,34 +137,16 @@ emails, account numbers, or PII).
|
|
|
103
137
|
pip install django-admin-react
|
|
104
138
|
```
|
|
105
139
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
INSTALLED_APPS
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
"django.contrib.messages",
|
|
114
|
-
"django.contrib.staticfiles",
|
|
115
|
-
"django_admin_react", # ← add this
|
|
116
|
-
# ... your own apps
|
|
117
|
-
]
|
|
118
|
-
```
|
|
140
|
+
This pulls in the JSON API ([`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/))
|
|
141
|
+
and the MCP adapter ([`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/))
|
|
142
|
+
as transitive dependencies. The **two-line `INSTALLED_APPS` + one-line
|
|
143
|
+
URL include** at the top of this README is the *entire* integration.
|
|
144
|
+
Mount at any prefix you like — `/admin-react/`, `/staff/`,
|
|
145
|
+
`/back-office/` — just don't collide with `django.contrib.admin`'s
|
|
146
|
+
own mount.
|
|
119
147
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
from django.urls import include, path
|
|
123
|
-
|
|
124
|
-
urlpatterns = [
|
|
125
|
-
path("admin/", include("django_admin_react.urls")),
|
|
126
|
-
# any prefix is fine:
|
|
127
|
-
# path("admin-react/", include("django_admin_react.urls")),
|
|
128
|
-
# path("staff/", include("django_admin_react.urls")),
|
|
129
|
-
]
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
That is the entire integration. Log in as a staff user → modern,
|
|
133
|
-
Tailwind-styled SPA driven by your existing `ModelAdmin` classes.
|
|
148
|
+
Log in as a staff user → modern, Tailwind-styled SPA driven by your
|
|
149
|
+
existing `ModelAdmin` classes.
|
|
134
150
|
|
|
135
151
|
The wheel ships the **pre-built React bundle**. You do **not** need
|
|
136
152
|
Node, pnpm, or any frontend toolchain to install or run.
|
|
@@ -159,6 +175,16 @@ DJANGO_ADMIN_REACT = {
|
|
|
159
175
|
# active states. Hex only (validated);
|
|
160
176
|
# injected as the --dar-primary CSS var, so
|
|
161
177
|
# rebranding needs no React rebuild.
|
|
178
|
+
|
|
179
|
+
# Auth + API mount
|
|
180
|
+
"REACT_LOGIN": True, # bool — React-rendered login is the default;
|
|
181
|
+
# the SPA shell is served to anonymous users
|
|
182
|
+
# and posts to /api/v1/login/. Set False to
|
|
183
|
+
# opt back into the legacy admin HTML login.
|
|
184
|
+
"API_URL_PREFIX": None, # str | None — point the SPA at a separately-
|
|
185
|
+
# mounted django-admin-rest-api (e.g.
|
|
186
|
+
# "/api/api/v1/"). Default None keeps the
|
|
187
|
+
# inline include the package ships today.
|
|
162
188
|
}
|
|
163
189
|
```
|
|
164
190
|
|
|
@@ -462,8 +488,9 @@ register_field_type(MoneyField, vocab_type="decimal")
|
|
|
462
488
|
# code required.
|
|
463
489
|
```
|
|
464
490
|
|
|
465
|
-
|
|
466
|
-
|
|
491
|
+
Coining a brand-new `vocab_type` (with a matching SPA widget) is an
|
|
492
|
+
**API-repo** concern — open the issue at
|
|
493
|
+
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api).
|
|
467
494
|
|
|
468
495
|
### Pre-built `get_*` overrides still work
|
|
469
496
|
|
|
@@ -510,7 +537,6 @@ and the [project board](https://github.com/users/MartinCastroAlvarez/projects/3)
|
|
|
510
537
|
✅ = shipped in the current alpha. 🟡 = not yet built (tracked). This
|
|
511
538
|
column is the **backend** capability only — for which surfaces the React
|
|
512
539
|
UI renders today, see the [frontend tracker (#160)](https://github.com/MartinCastroAlvarez/django-admin-react/issues/160).
|
|
513
|
-
[`ACCEPTANCE.md`](ACCEPTANCE.md) carries the full criterion-by-criterion list.
|
|
514
540
|
|
|
515
541
|
---
|
|
516
542
|
|
|
@@ -535,8 +561,9 @@ frontend, a script).
|
|
|
535
561
|
|
|
536
562
|
Every endpoint is **staff-only by default** (or whatever
|
|
537
563
|
`AdminSite.has_permission` returns), CSRF-required on unsafe
|
|
538
|
-
methods, and emits `Cache-Control: no-store`. Full wire contract
|
|
539
|
-
|
|
564
|
+
methods, and emits `Cache-Control: no-store`. Full wire contract
|
|
565
|
+
lives in the API repo:
|
|
566
|
+
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api).
|
|
540
567
|
|
|
541
568
|
---
|
|
542
569
|
|
|
@@ -600,6 +627,10 @@ See [`SECURITY.md`](SECURITY.md). Do **not** open a public issue.
|
|
|
600
627
|
|
|
601
628
|
## Contributing
|
|
602
629
|
|
|
603
|
-
|
|
604
|
-
[
|
|
630
|
+
Open an [Issue](https://github.com/MartinCastroAlvarez/django-admin-react/issues/new)
|
|
631
|
+
or a [Discussion](https://github.com/MartinCastroAlvarez/django-admin-react/discussions)
|
|
632
|
+
before sending a PR for anything non-trivial. **API-side contributions** (any
|
|
633
|
+
`/api/v1/...` endpoint, the wire contract, permission gates, serializer
|
|
634
|
+
denylist) go to [`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api)
|
|
635
|
+
— this repo owns only the **React SPA super-layer** on top.
|
|
605
636
|
|
|
@@ -4,11 +4,43 @@ A drop-in **React single-page admin** for any Django 5+ project. Same
|
|
|
4
4
|
`pip install`, same `INSTALLED_APPS`, same `urls.py include()` — and
|
|
5
5
|
your `ModelAdmin` classes drive everything. No React code on your side.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
```python
|
|
8
|
+
# settings.py
|
|
9
|
+
INSTALLED_APPS = [
|
|
10
|
+
# ...
|
|
11
|
+
"django.contrib.admin",
|
|
12
|
+
"django_admin_react", # the React SPA — includes the JSON API for you
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
# urls.py
|
|
16
|
+
urlpatterns = [
|
|
17
|
+
path("admin/", admin.site.urls),
|
|
18
|
+
path("admin-react/", include("django_admin_react.urls")), # SPA + API in one include
|
|
19
|
+
]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**One `INSTALLED_APPS` line + one URL include is the entire integration.** `pip install django-admin-react` transitively pulls in the [JSON API](https://pypi.org/project/django-admin-rest-api/) and the [MCP adapter](https://pypi.org/project/django-admin-mcp-api/); `django_admin_react.urls` includes the API endpoints at `<mount>/api/v1/…`, so the SPA finds its wire surface with zero configuration. (Mount the API a second time at your own prefix only if a non-SPA client also needs it.)
|
|
23
|
+
|
|
24
|
+
> **Beta — v1.0.0.** Available on PyPI; the SPA + the API
|
|
25
|
+
> ([`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/))
|
|
26
|
+
> + the MCP adapter
|
|
27
|
+
> ([`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/))
|
|
28
|
+
> all share the v1 wire contract. Track progress on the
|
|
9
29
|
> [Project board](https://github.com/users/MartinCastroAlvarez/projects/3)
|
|
10
30
|
> and the [Issues list](https://github.com/MartinCastroAlvarez/django-admin-react/issues).
|
|
11
31
|
|
|
32
|
+
## Three repos, one product
|
|
33
|
+
|
|
34
|
+
The project is split into three independently-published, cross-referenced repos so each piece can be consumed on its own merits:
|
|
35
|
+
|
|
36
|
+
| Repo | PyPI | Role |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| **[`django-admin-rest-api`](https://github.com/MartinCastroAlvarez/django-admin-api)** | [`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/) | The JSON REST API for the Django admin — same permissions, same `ModelAdmin`, no new features. The wire surface. |
|
|
39
|
+
| **`django-admin-react`** *(this repo)* | [`django-admin-react`](https://pypi.org/project/django-admin-react/) | The React SPA frontend. A **super-layer** that depends on `django-admin-rest-api` for every wire call. |
|
|
40
|
+
| **[`django-admin-mcp-api`](https://github.com/MartinCastroAlvarez/django-admin-mcp)** | [`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/) | Wire-protocol-only **MCP** adapter (call, manifest, …) over `django-admin-rest-api` — lets agents reach the same `ModelAdmin`-driven REST surface, no new functionality / permissions / validation. |
|
|
41
|
+
|
|
42
|
+
The wire contract itself lives in the **API repo** (`docs/api-contract.md` there). This README is about the SPA. The migration from "self-contained" to the 3-repo split is tracked in [META #544](https://github.com/MartinCastroAlvarez/django-admin-react/issues/544).
|
|
43
|
+
|
|
12
44
|
---
|
|
13
45
|
|
|
14
46
|
## Why django-admin-react
|
|
@@ -46,8 +78,8 @@ permissions at runtime from `GET /api/v1/registry/`. Add a new
|
|
|
46
78
|
|
|
47
79
|
Real captures of the **django-admin-react SPA** rendering the bundled
|
|
48
80
|
`examples/` apps — driven entirely by each app's `ModelAdmin`.
|
|
49
|
-
|
|
50
|
-
|
|
81
|
+
Captured **manually** against a local dev server (no Playwright / Cypress /
|
|
82
|
+
e2e tooling required).
|
|
51
83
|
|
|
52
84
|
| Sign in (package login) | Registry / home |
|
|
53
85
|
| -------------------------------------------------- | ----------------------------------------------------- |
|
|
@@ -72,34 +104,16 @@ emails, account numbers, or PII).
|
|
|
72
104
|
pip install django-admin-react
|
|
73
105
|
```
|
|
74
106
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
INSTALLED_APPS
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"django.contrib.messages",
|
|
83
|
-
"django.contrib.staticfiles",
|
|
84
|
-
"django_admin_react", # ← add this
|
|
85
|
-
# ... your own apps
|
|
86
|
-
]
|
|
87
|
-
```
|
|
107
|
+
This pulls in the JSON API ([`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/))
|
|
108
|
+
and the MCP adapter ([`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/))
|
|
109
|
+
as transitive dependencies. The **two-line `INSTALLED_APPS` + one-line
|
|
110
|
+
URL include** at the top of this README is the *entire* integration.
|
|
111
|
+
Mount at any prefix you like — `/admin-react/`, `/staff/`,
|
|
112
|
+
`/back-office/` — just don't collide with `django.contrib.admin`'s
|
|
113
|
+
own mount.
|
|
88
114
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
from django.urls import include, path
|
|
92
|
-
|
|
93
|
-
urlpatterns = [
|
|
94
|
-
path("admin/", include("django_admin_react.urls")),
|
|
95
|
-
# any prefix is fine:
|
|
96
|
-
# path("admin-react/", include("django_admin_react.urls")),
|
|
97
|
-
# path("staff/", include("django_admin_react.urls")),
|
|
98
|
-
]
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
That is the entire integration. Log in as a staff user → modern,
|
|
102
|
-
Tailwind-styled SPA driven by your existing `ModelAdmin` classes.
|
|
115
|
+
Log in as a staff user → modern, Tailwind-styled SPA driven by your
|
|
116
|
+
existing `ModelAdmin` classes.
|
|
103
117
|
|
|
104
118
|
The wheel ships the **pre-built React bundle**. You do **not** need
|
|
105
119
|
Node, pnpm, or any frontend toolchain to install or run.
|
|
@@ -128,6 +142,16 @@ DJANGO_ADMIN_REACT = {
|
|
|
128
142
|
# active states. Hex only (validated);
|
|
129
143
|
# injected as the --dar-primary CSS var, so
|
|
130
144
|
# rebranding needs no React rebuild.
|
|
145
|
+
|
|
146
|
+
# Auth + API mount
|
|
147
|
+
"REACT_LOGIN": True, # bool — React-rendered login is the default;
|
|
148
|
+
# the SPA shell is served to anonymous users
|
|
149
|
+
# and posts to /api/v1/login/. Set False to
|
|
150
|
+
# opt back into the legacy admin HTML login.
|
|
151
|
+
"API_URL_PREFIX": None, # str | None — point the SPA at a separately-
|
|
152
|
+
# mounted django-admin-rest-api (e.g.
|
|
153
|
+
# "/api/api/v1/"). Default None keeps the
|
|
154
|
+
# inline include the package ships today.
|
|
131
155
|
}
|
|
132
156
|
```
|
|
133
157
|
|
|
@@ -431,8 +455,9 @@ register_field_type(MoneyField, vocab_type="decimal")
|
|
|
431
455
|
# code required.
|
|
432
456
|
```
|
|
433
457
|
|
|
434
|
-
|
|
435
|
-
|
|
458
|
+
Coining a brand-new `vocab_type` (with a matching SPA widget) is an
|
|
459
|
+
**API-repo** concern — open the issue at
|
|
460
|
+
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api).
|
|
436
461
|
|
|
437
462
|
### Pre-built `get_*` overrides still work
|
|
438
463
|
|
|
@@ -479,7 +504,6 @@ and the [project board](https://github.com/users/MartinCastroAlvarez/projects/3)
|
|
|
479
504
|
✅ = shipped in the current alpha. 🟡 = not yet built (tracked). This
|
|
480
505
|
column is the **backend** capability only — for which surfaces the React
|
|
481
506
|
UI renders today, see the [frontend tracker (#160)](https://github.com/MartinCastroAlvarez/django-admin-react/issues/160).
|
|
482
|
-
[`ACCEPTANCE.md`](ACCEPTANCE.md) carries the full criterion-by-criterion list.
|
|
483
507
|
|
|
484
508
|
---
|
|
485
509
|
|
|
@@ -504,8 +528,9 @@ frontend, a script).
|
|
|
504
528
|
|
|
505
529
|
Every endpoint is **staff-only by default** (or whatever
|
|
506
530
|
`AdminSite.has_permission` returns), CSRF-required on unsafe
|
|
507
|
-
methods, and emits `Cache-Control: no-store`. Full wire contract
|
|
508
|
-
|
|
531
|
+
methods, and emits `Cache-Control: no-store`. Full wire contract
|
|
532
|
+
lives in the API repo:
|
|
533
|
+
[`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api).
|
|
509
534
|
|
|
510
535
|
---
|
|
511
536
|
|
|
@@ -569,5 +594,9 @@ See [`SECURITY.md`](SECURITY.md). Do **not** open a public issue.
|
|
|
569
594
|
|
|
570
595
|
## Contributing
|
|
571
596
|
|
|
572
|
-
|
|
573
|
-
[
|
|
597
|
+
Open an [Issue](https://github.com/MartinCastroAlvarez/django-admin-react/issues/new)
|
|
598
|
+
or a [Discussion](https://github.com/MartinCastroAlvarez/django-admin-react/discussions)
|
|
599
|
+
before sending a PR for anything non-trivial. **API-side contributions** (any
|
|
600
|
+
`/api/v1/...` endpoint, the wire contract, permission gates, serializer
|
|
601
|
+
denylist) go to [`MartinCastroAlvarez/django-admin-api`](https://github.com/MartinCastroAlvarez/django-admin-api)
|
|
602
|
+
— this repo owns only the **React SPA super-layer** on top.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""django-admin-react — the React SPA super-layer for the Django admin.
|
|
2
|
+
|
|
3
|
+
A drop-in single-page admin: same `pip install`, same `INSTALLED_APPS`,
|
|
4
|
+
same `urls.py include()` — and your `ModelAdmin` classes drive everything.
|
|
5
|
+
The JSON wire surface lives in the sibling
|
|
6
|
+
[`django-admin-rest-api`](https://pypi.org/project/django-admin-rest-api/)
|
|
7
|
+
package (pulled in as a dependency); the MCP exposure of the same surface
|
|
8
|
+
lives in
|
|
9
|
+
[`django-admin-mcp-api`](https://pypi.org/project/django-admin-mcp-api/).
|
|
10
|
+
|
|
11
|
+
See `README.md` for install + the consumer wiring, and `ARCHITECTURE.md`
|
|
12
|
+
for what lives in this repo vs. the API / MCP siblings.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from importlib.metadata import PackageNotFoundError
|
|
16
|
+
from importlib.metadata import version as _pkg_version
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
# Read the version directly from the installed distribution metadata
|
|
20
|
+
# so this constant never drifts from `pyproject.toml` after a release.
|
|
21
|
+
__version__ = _pkg_version("django-admin-react")
|
|
22
|
+
except PackageNotFoundError: # pragma: no cover — editable / source install
|
|
23
|
+
__version__ = "0.0.0"
|
|
24
|
+
|
|
25
|
+
default_app_config = "django_admin_react.apps.DjangoAdminReactConfig"
|
|
@@ -17,6 +17,8 @@ Public surface:
|
|
|
17
17
|
|
|
18
18
|
- :func:`object_log_entries` — the ``LogEntry`` queryset for one object,
|
|
19
19
|
newest-first, with the acting user pre-fetched.
|
|
20
|
+
- :func:`recent_actions_for_user` — the most recent ``LogEntry`` rows for
|
|
21
|
+
one user (the index "Recent actions" panel), newest-first.
|
|
20
22
|
"""
|
|
21
23
|
|
|
22
24
|
from __future__ import annotations
|
|
@@ -40,3 +42,17 @@ def object_log_entries(obj: Model) -> QuerySet[LogEntry]:
|
|
|
40
42
|
.select_related("user")
|
|
41
43
|
.order_by("-action_time")
|
|
42
44
|
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def recent_actions_for_user(user_pk: str | int, limit: int) -> QuerySet[LogEntry]:
|
|
48
|
+
"""Return the most recent ``LogEntry`` rows for one user, newest first.
|
|
49
|
+
|
|
50
|
+
The user-scoped counterpart of :func:`object_log_entries`: filtered by
|
|
51
|
+
the acting user and capped at ``limit`` — exactly how Django's admin
|
|
52
|
+
index "Recent actions" panel reads the log
|
|
53
|
+
(``LogEntry.objects.filter(user=...)``). Same get_queryset-rule
|
|
54
|
+
rationale as the module docstring: LogEntry is a framework audit
|
|
55
|
+
table, not a consumer model, so it is read directly here (outside
|
|
56
|
+
``api/``) rather than via ``ModelAdmin.get_queryset``.
|
|
57
|
+
"""
|
|
58
|
+
return LogEntry.objects.filter(user__pk=user_pk).order_by("-action_time")[:limit]
|
|
@@ -62,19 +62,20 @@ DEFAULTS: dict[str, Any] = {
|
|
|
62
62
|
# falls back to this default, since the value is written into a
|
|
63
63
|
# ``<style>`` block and must not be able to inject CSS.
|
|
64
64
|
"PRIMARY_COLOR": "#2563eb",
|
|
65
|
-
# ``REACT_LOGIN`` —
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
# (
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
|
|
65
|
+
# ``REACT_LOGIN`` — React-rendered login is the **default** so the
|
|
66
|
+
# SPA fully replaces the Django admin URL surface end-to-end (owner
|
|
67
|
+
# directive 2026-05-28). ``SpaIndexView`` serves the React shell to
|
|
68
|
+
# anonymous users (with the CSRF cookie set) and the in-SPA login
|
|
69
|
+
# form POSTs to the API package's ``/api/v1/login/``. A consumer
|
|
70
|
+
# who wants the legacy HTML-admin login back can opt out with
|
|
71
|
+
# ``"REACT_LOGIN": False`` — the package's own ``<mount>/login/``
|
|
72
|
+
# endpoint is still mounted in either mode. The auth *mechanism* is
|
|
73
|
+
# unchanged in both modes (Django's ``authenticate``/``login``
|
|
74
|
+
# behind the JSON endpoint); only the UI surface differs. The
|
|
75
|
+
# shell carries no user data — serving it to anonymous users
|
|
76
|
+
# discloses nothing the static bundle wouldn't, and every data API
|
|
77
|
+
# call still returns 403 until the user authenticates.
|
|
78
|
+
"REACT_LOGIN": True,
|
|
78
79
|
# PWA (Issue #86) — all optional; sane defaults make the manifest
|
|
79
80
|
# work with zero config. See ``django_admin_react/pwa.py`` +
|
|
80
81
|
# ``docs/ux/pwa.md``.
|
|
@@ -87,6 +88,17 @@ DEFAULTS: dict[str, Any] = {
|
|
|
87
88
|
# dicts. ``None`` (default) uses the shipped
|
|
88
89
|
# 192/512/maskable set under
|
|
89
90
|
# ``static/dar/icons/``.
|
|
91
|
+
# ``API_URL_PREFIX`` — absolute URL prefix the SPA calls for every
|
|
92
|
+
# JSON request (#559). Default ``None`` keeps the inline include the
|
|
93
|
+
# package ships today (`<spa-mount>/api/v1/`), so existing consumers
|
|
94
|
+
# are unaffected. Override when the consumer mounts
|
|
95
|
+
# ``django_admin_rest_api.urls`` separately and the SPA should talk
|
|
96
|
+
# to **that** mount instead — for example
|
|
97
|
+
# ``DJANGO_ADMIN_REACT = {"API_URL_PREFIX": "/api/api/v1/"}`` lets
|
|
98
|
+
# the SPA and any other client share a single REST mount. When set,
|
|
99
|
+
# `django_admin_react.urls` skips the inline `api/v1/` include so
|
|
100
|
+
# there is no double-mount.
|
|
101
|
+
"API_URL_PREFIX": None,
|
|
90
102
|
"PWA_NAME": None,
|
|
91
103
|
"PWA_SHORT_NAME": None,
|
|
92
104
|
"PWA_ICONS": None,
|
|
@@ -109,6 +121,7 @@ class _PackageSettings:
|
|
|
109
121
|
BRAND_LOGO_URL: str | None = DEFAULTS["BRAND_LOGO_URL"]
|
|
110
122
|
PRIMARY_COLOR: str = DEFAULTS["PRIMARY_COLOR"]
|
|
111
123
|
REACT_LOGIN: bool = DEFAULTS["REACT_LOGIN"]
|
|
124
|
+
API_URL_PREFIX: str | None = DEFAULTS["API_URL_PREFIX"]
|
|
112
125
|
PWA_NAME: str | None = DEFAULTS["PWA_NAME"]
|
|
113
126
|
PWA_SHORT_NAME: str | None = DEFAULTS["PWA_SHORT_NAME"]
|
|
114
127
|
PWA_ICONS: list[dict[str, str]] | None = DEFAULTS["PWA_ICONS"]
|
|
@@ -34,7 +34,11 @@ from django.shortcuts import render
|
|
|
34
34
|
from django.views.generic import View
|
|
35
35
|
|
|
36
36
|
from django_admin_react import conf as dar_conf
|
|
37
|
-
|
|
37
|
+
|
|
38
|
+
# Re-use the API package's admin-site lookup (this repo implements no
|
|
39
|
+
# API; the registry helper lives there). The PWA only needs the active
|
|
40
|
+
# `AdminSite.name` for the manifest's start URL.
|
|
41
|
+
from django_admin_rest_api.api.registry import get_admin_site
|
|
38
42
|
|
|
39
43
|
# Theme colours keyed by the resolved colour scheme. Kept here (not in
|
|
40
44
|
# the SPA's CSS-var system) because the manifest is rendered server-side
|