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.
Files changed (53) hide show
  1. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/PKG-INFO +71 -40
  2. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/README.md +67 -38
  3. django_admin_react-1.0.1/django_admin_react/__init__.py +25 -0
  4. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/audit.py +16 -0
  5. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/conf.py +26 -13
  6. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/pwa.py +5 -1
  7. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/static/admin_react/.vite/manifest.json +2 -2
  8. django_admin_react-1.0.1/django_admin_react/static/admin_react/assets/index-CDjd0bZa.js +8 -0
  9. django_admin_react-1.0.1/django_admin_react/static/admin_react/assets/index-Fn2O5Tqj.css +1 -0
  10. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/static/admin_react/index.html +2 -2
  11. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/admin_react/index.html +7 -0
  12. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/urls.py +33 -11
  13. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/views.py +41 -3
  14. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/pyproject.toml +14 -2
  15. django_admin_react-0.2.0a8/django_admin_react/__init__.py +0 -10
  16. django_admin_react-0.2.0a8/django_admin_react/api/README.md +0 -31
  17. django_admin_react-0.2.0a8/django_admin_react/api/__init__.py +0 -5
  18. django_admin_react-0.2.0a8/django_admin_react/api/dates.py +0 -215
  19. django_admin_react-0.2.0a8/django_admin_react/api/filters.py +0 -412
  20. django_admin_react-0.2.0a8/django_admin_react/api/inlines.py +0 -358
  21. django_admin_react-0.2.0a8/django_admin_react/api/inlines_write.py +0 -241
  22. django_admin_react-0.2.0a8/django_admin_react/api/panels.py +0 -113
  23. django_admin_react-0.2.0a8/django_admin_react/api/permissions.py +0 -132
  24. django_admin_react-0.2.0a8/django_admin_react/api/registry.py +0 -399
  25. django_admin_react-0.2.0a8/django_admin_react/api/serializers.py +0 -467
  26. django_admin_react-0.2.0a8/django_admin_react/api/urls.py +0 -164
  27. django_admin_react-0.2.0a8/django_admin_react/api/views/README.md +0 -22
  28. django_admin_react-0.2.0a8/django_admin_react/api/views/__init__.py +0 -6
  29. django_admin_react-0.2.0a8/django_admin_react/api/views/actions.py +0 -196
  30. django_admin_react-0.2.0a8/django_admin_react/api/views/auth.py +0 -192
  31. django_admin_react-0.2.0a8/django_admin_react/api/views/autocomplete.py +0 -163
  32. django_admin_react-0.2.0a8/django_admin_react/api/views/bulk.py +0 -248
  33. django_admin_react-0.2.0a8/django_admin_react/api/views/create.py +0 -213
  34. django_admin_react-0.2.0a8/django_admin_react/api/views/create_form.py +0 -229
  35. django_admin_react-0.2.0a8/django_admin_react/api/views/delete_preview.py +0 -107
  36. django_admin_react-0.2.0a8/django_admin_react/api/views/destroy.py +0 -93
  37. django_admin_react-0.2.0a8/django_admin_react/api/views/detail.py +0 -482
  38. django_admin_react-0.2.0a8/django_admin_react/api/views/history.py +0 -166
  39. django_admin_react-0.2.0a8/django_admin_react/api/views/list.py +0 -493
  40. django_admin_react-0.2.0a8/django_admin_react/api/views/password.py +0 -161
  41. django_admin_react-0.2.0a8/django_admin_react/api/views/registry.py +0 -53
  42. django_admin_react-0.2.0a8/django_admin_react/api/views/schema.py +0 -494
  43. django_admin_react-0.2.0a8/django_admin_react/api/views/update.py +0 -220
  44. django_admin_react-0.2.0a8/django_admin_react/api/writes.py +0 -457
  45. django_admin_react-0.2.0a8/django_admin_react/static/admin_react/assets/index-BSzI7RU6.css +0 -1
  46. django_admin_react-0.2.0a8/django_admin_react/static/admin_react/assets/index-CxlHfz-w.js +0 -8
  47. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/LICENSE +0 -0
  48. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/README.md +0 -0
  49. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/apps.py +0 -0
  50. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/README.md +0 -0
  51. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/admin_react/README.md +0 -0
  52. {django_admin_react-0.2.0a8 → django_admin_react-1.0.1}/django_admin_react/templates/admin_react/login.html +0 -0
  53. {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.2.0a8
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 :: 2 - Pre-Alpha
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
- > **Pre-alpha.** Available on PyPI as an alpha. Pin tightly; expect
39
- > breaking changes between alpha releases. Track progress on the
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
- Regenerate any time with `scripts/screenshots.sh` (Playwright against a
81
- throwaway example server).
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
- ```python
107
- # settings.py
108
- INSTALLED_APPS = [
109
- "django.contrib.admin",
110
- "django.contrib.auth",
111
- "django.contrib.contenttypes",
112
- "django.contrib.sessions",
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
- ```python
121
- # urls.py
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
- For coining a brand-new `vocab_type` (with a matching SPA widget)
466
- see [`docs/extensions.md`](docs/extensions.md).
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
- [`docs/api-contract.md`](docs/api-contract.md).
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
- Humans and AI agents both welcome. Start with
604
- [`CONTRIBUTING.md`](CONTRIBUTING.md).
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
- > **Pre-alpha.** Available on PyPI as an alpha. Pin tightly; expect
8
- > breaking changes between alpha releases. Track progress on the
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
- Regenerate any time with `scripts/screenshots.sh` (Playwright against a
50
- throwaway example server).
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
- ```python
76
- # settings.py
77
- INSTALLED_APPS = [
78
- "django.contrib.admin",
79
- "django.contrib.auth",
80
- "django.contrib.contenttypes",
81
- "django.contrib.sessions",
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
- ```python
90
- # urls.py
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
- For coining a brand-new `vocab_type` (with a matching SPA widget)
435
- see [`docs/extensions.md`](docs/extensions.md).
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
- [`docs/api-contract.md`](docs/api-contract.md).
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
- Humans and AI agents both welcome. Start with
573
- [`CONTRIBUTING.md`](CONTRIBUTING.md).
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`` — opt-in React-rendered login (Issue #167).
66
- # Default ``False`` keeps today's behavior: ``SpaIndexView``
67
- # redirects anonymous / unauthorized users to Django's HTML login
68
- # (or the package's own ``<mount>/login/`` page). When ``True``,
69
- # the SPA shell is served to anonymous users (with the CSRF cookie
70
- # set) so the React app can render its own login form, which POSTs
71
- # to ``/api/v1/login/``. The auth *mechanism* is unchanged — still
72
- # Django's ``authenticate``/``login`` behind the JSON endpoint
73
- # (`api/views/auth.py`); only the UI surface differs. The shell
74
- # carries no user data, so serving it to anonymous users discloses
75
- # nothing the static bundle wouldn't, and every data API call still
76
- # returns 403 until the user authenticates.
77
- "REACT_LOGIN": False,
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
- from django_admin_react.api.registry import get_admin_site
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
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "index.html": {
3
- "file": "assets/index-CxlHfz-w.js",
3
+ "file": "assets/index-CDjd0bZa.js",
4
4
  "name": "index",
5
5
  "src": "index.html",
6
6
  "isEntry": true,
7
7
  "css": [
8
- "assets/index-BSzI7RU6.css"
8
+ "assets/index-Fn2O5Tqj.css"
9
9
  ]
10
10
  }
11
11
  }