|
2 | 2 |
|
3 | 3 | **Manage your app with a backend interface.**
|
4 | 4 |
|
5 |
| -The Plain Admin provides a combination of built-in views and the flexibility to create your own. You can use it to quickly get visibility into your app's data and to manage it. |
6 |
| - |
7 |
| - |
| 5 | +- [Overview](#overview) |
| 6 | +- [Admin viewsets](#admin-viewsets) |
| 7 | +- [Admin cards](#admin-cards) |
| 8 | +- [Admin forms](#admin-forms) |
| 9 | +- [List displays](#list-displays) |
| 10 | +- [Toolbar](#toolbar) |
| 11 | +- [Impersonate](#impersonate) |
| 12 | +- [Installation](#installation) |
8 | 13 |
|
9 |
| -## Installation |
10 |
| - |
11 |
| -Install the `plain.admin` package and its dependencies. |
| 14 | +## Overview |
12 | 15 |
|
13 |
| -```console |
14 |
| -uv add plain.admin |
15 |
| -``` |
16 |
| - |
17 |
| -The admin uses a combination of other Plain packages, most of which you will already have installed. Ultimately, your settings will look something like this: |
18 |
| - |
19 |
| -```python |
20 |
| -# app/settings.py |
21 |
| -INSTALLED_PACKAGES = [ |
22 |
| - "plain.models", |
23 |
| - "plain.tailwind", |
24 |
| - "plain.auth", |
25 |
| - "plain.sessions", |
26 |
| - "plain.htmx", |
27 |
| - "plain.admin", |
28 |
| - "plain.elements", |
29 |
| - # other packages... |
30 |
| -] |
31 |
| - |
32 |
| -AUTH_USER_MODEL = "users.User" |
33 |
| -AUTH_LOGIN_URL = "login" |
34 |
| - |
35 |
| -MIDDLEWARE = [ |
36 |
| - "plain.sessions.middleware.SessionMiddleware", |
37 |
| - "plain.auth.middleware.AuthenticationMiddleware", |
38 |
| - "plain.admin.AdminMiddleware", |
39 |
| -] |
40 |
| -``` |
41 |
| - |
42 |
| -Your User model is expected to have an `is_admin` field (or attribute) for checking who has permission to access the admin. |
43 |
| - |
44 |
| -```python |
45 |
| -# app/users/models.py |
46 |
| -from plain import models |
47 |
| - |
48 |
| - |
49 |
| -@models.register_model |
50 |
| -class User(models.Model): |
51 |
| - is_admin = models.BooleanField(default=False) |
52 |
| - # other fields... |
53 |
| -``` |
54 |
| - |
55 |
| -To make the admin accessible, add the `AdminRouter` to your root URLs. |
56 |
| - |
57 |
| -```python |
58 |
| -# app/urls.py |
59 |
| -from plain.admin.urls import AdminRouter |
60 |
| -from plain.urls import Router, include, path |
61 |
| - |
62 |
| -from . import views |
63 |
| - |
64 |
| - |
65 |
| -class AppRouter(Router): |
66 |
| - namespace = "" |
67 |
| - urls = [ |
68 |
| - include("admin/", AdminRouter), |
69 |
| - path("login/", views.LoginView, name="login"), |
70 |
| - path("logout/", LogoutView, name="logout"), |
71 |
| - # other urls... |
72 |
| - ] |
73 |
| - |
74 |
| -``` |
75 |
| - |
76 |
| -Optionally, you can add the admin toolbar to your base template. The toolbar will appear when `settings.DEBUG` or when `request.user.is_admin` (including in production!). |
77 |
| - |
78 |
| -```html |
79 |
| -<!-- app/templates/base.html --> |
80 |
| -<!DOCTYPE html> |
81 |
| -<html lang="en"> |
82 |
| -<head> |
83 |
| - <meta charset="UTF-8"> |
84 |
| - <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
85 |
| - <title>{{ html_title|default("My App") }}</title> |
86 |
| - {% tailwind_css %} |
87 |
| -</head> |
88 |
| -<body> |
89 |
| - {% block content required %}{% endblock %} |
90 |
| - |
91 |
| - {% toolbar %} |
92 |
| -</body> |
93 |
| -</html> |
94 |
| -``` |
| 16 | +The Plain Admin provides a combination of built-in views and the flexibility to create your own. You can use it to quickly get visibility into your app's data and to manage it. |
95 | 17 |
|
96 |
| -## Admin viewsets |
| 18 | + |
97 | 19 |
|
98 |
| -The most common use of the admin is to display and manage your `plain.models`. To do this, create a viewset with a set of inner views. |
| 20 | +The most common use of the admin is to manage your `plain.models`. To do this, create a [viewset](./views/viewsets.py#AdminViewset) with inner/nested views: |
99 | 21 |
|
100 | 22 | ```python
|
101 | 23 | # app/users/admin.py
|
@@ -140,7 +62,9 @@ class UserAdmin(AdminViewset):
|
140 | 62 | form_class = UserForm
|
141 | 63 | ```
|
142 | 64 |
|
143 |
| -The [`AdminViewset`](./views/viewsets.py) will automatically recognize inner views named `ListView`, `CreateView`, `DetailView`, `UpdateView`, and `DeleteView`. It will interlink these views automatically in the UI and form success URLs. You can define additional views too, but you will need to implement a couple methods to hook them up. |
| 65 | +## Admin viewsets |
| 66 | + |
| 67 | +The [`AdminViewset`](./views/viewsets.py#AdminViewset) will automatically recognize inner views named `ListView`, `CreateView`, `DetailView`, `UpdateView`, and `DeleteView`. It will interlink these views automatically in the UI and form success URLs. You can define additional views too, but you will need to implement a couple methods to hook them up. |
144 | 68 |
|
145 | 69 | ## Admin cards
|
146 | 70 |
|
|
150 | 74 |
|
151 | 75 | TODO
|
152 | 76 |
|
153 |
| -## List `displays` |
| 77 | +## List displays |
154 | 78 |
|
155 |
| -On admin list views, you can define different `displays` to build predefined views of your data. The display choices will be shown in the UI, and you can use the current `self.display` in your view. |
| 79 | +On [`AdminListView`](./views/objects.py#AdminListView) and [`AdminModelListView`](./views/models.py#AdminModelListView), you can define different `displays` to build predefined views of your data. The display choices will be shown in the UI, and you can use the current `self.display` in your view logic. |
156 | 80 |
|
157 | 81 | ```python
|
158 | 82 | # app/users/admin.py
|
@@ -188,3 +112,89 @@ TODO
|
188 | 112 | ## Impersonate
|
189 | 113 |
|
190 | 114 | TODO
|
| 115 | + |
| 116 | +## Installation |
| 117 | + |
| 118 | +Install the `plain.admin` package from [PyPI](https://pypi.org/project/plain.admin/): |
| 119 | + |
| 120 | +```bash |
| 121 | +uv add plain.admin |
| 122 | +``` |
| 123 | + |
| 124 | +The admin uses a combination of other Plain packages, most of which you will already have installed. Ultimately, your settings will look something like this: |
| 125 | + |
| 126 | +```python |
| 127 | +# app/settings.py |
| 128 | +INSTALLED_PACKAGES = [ |
| 129 | + "plain.models", |
| 130 | + "plain.tailwind", |
| 131 | + "plain.auth", |
| 132 | + "plain.sessions", |
| 133 | + "plain.htmx", |
| 134 | + "plain.admin", |
| 135 | + "plain.elements", |
| 136 | + # other packages... |
| 137 | +] |
| 138 | + |
| 139 | +AUTH_USER_MODEL = "users.User" |
| 140 | +AUTH_LOGIN_URL = "login" |
| 141 | + |
| 142 | +MIDDLEWARE = [ |
| 143 | + "plain.sessions.middleware.SessionMiddleware", |
| 144 | + "plain.auth.middleware.AuthenticationMiddleware", |
| 145 | + "plain.admin.AdminMiddleware", |
| 146 | +] |
| 147 | +``` |
| 148 | + |
| 149 | +Your User model is expected to have an `is_admin` field (or attribute) for checking who has permission to access the admin. |
| 150 | + |
| 151 | +```python |
| 152 | +# app/users/models.py |
| 153 | +from plain import models |
| 154 | + |
| 155 | + |
| 156 | +@models.register_model |
| 157 | +class User(models.Model): |
| 158 | + is_admin = models.BooleanField(default=False) |
| 159 | + # other fields... |
| 160 | +``` |
| 161 | + |
| 162 | +To make the admin accessible, add the [`AdminRouter`](./urls.py#AdminRouter) to your root URLs. |
| 163 | + |
| 164 | +```python |
| 165 | +# app/urls.py |
| 166 | +from plain.admin.urls import AdminRouter |
| 167 | +from plain.urls import Router, include, path |
| 168 | + |
| 169 | +from . import views |
| 170 | + |
| 171 | + |
| 172 | +class AppRouter(Router): |
| 173 | + namespace = "" |
| 174 | + urls = [ |
| 175 | + include("admin/", AdminRouter), |
| 176 | + path("login/", views.LoginView, name="login"), |
| 177 | + path("logout/", LogoutView, name="logout"), |
| 178 | + # other urls... |
| 179 | + ] |
| 180 | +``` |
| 181 | + |
| 182 | +Typically you will also want to add the admin `{% toolbar %}` to the bottom of your base template. The toolbar will appear when `settings.DEBUG` or when `request.user.is_admin` (including in production!). |
| 183 | + |
| 184 | +```html |
| 185 | +<!-- app/templates/base.html --> |
| 186 | +<!DOCTYPE html> |
| 187 | +<html lang="en"> |
| 188 | +<head> |
| 189 | + <meta charset="UTF-8"> |
| 190 | +<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 191 | + <title>{{ html_title|default("My App") }}</title> |
| 192 | + {% tailwind_css %} |
| 193 | +</head> |
| 194 | +<body> |
| 195 | + {% block content required %}{% endblock %} |
| 196 | + |
| 197 | + {% toolbar %} |
| 198 | +</body> |
| 199 | +</html> |
| 200 | +``` |
0 commit comments