|
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