plain.admin 0.56.0__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.
- plain_admin-0.56.0/.gitignore +21 -0
- plain_admin-0.56.0/LICENSE +28 -0
- plain_admin-0.56.0/PKG-INFO +193 -0
- plain_admin-0.56.0/README.md +1 -0
- plain_admin-0.56.0/plain/admin/CHANGELOG.md +464 -0
- plain_admin-0.56.0/plain/admin/README.md +179 -0
- plain_admin-0.56.0/plain/admin/__init__.py +5 -0
- plain_admin-0.56.0/plain/admin/assets/admin/admin.css +237 -0
- plain_admin-0.56.0/plain/admin/assets/admin/admin.js +212 -0
- plain_admin-0.56.0/plain/admin/assets/admin/bootstrap-icons.svg +1 -0
- plain_admin-0.56.0/plain/admin/assets/admin/list.js +94 -0
- plain_admin-0.56.0/plain/admin/assets/admin/vendor/chart.js +19 -0
- plain_admin-0.56.0/plain/admin/assets/admin/vendor/jquery-3.7.1.min.js +2 -0
- plain_admin-0.56.0/plain/admin/assets/admin/vendor/popper.min.js +5 -0
- plain_admin-0.56.0/plain/admin/assets/admin/vendor/tippy.css +1 -0
- plain_admin-0.56.0/plain/admin/assets/admin/vendor/tippy.umd.min.js +2 -0
- plain_admin-0.56.0/plain/admin/cards/__init__.py +10 -0
- plain_admin-0.56.0/plain/admin/cards/base.py +91 -0
- plain_admin-0.56.0/plain/admin/cards/charts.py +117 -0
- plain_admin-0.56.0/plain/admin/cards/tables.py +28 -0
- plain_admin-0.56.0/plain/admin/config.py +10 -0
- plain_admin-0.56.0/plain/admin/dates.py +268 -0
- plain_admin-0.56.0/plain/admin/impersonate/__init__.py +7 -0
- plain_admin-0.56.0/plain/admin/impersonate/constants.py +1 -0
- plain_admin-0.56.0/plain/admin/impersonate/middleware.py +44 -0
- plain_admin-0.56.0/plain/admin/impersonate/permissions.py +18 -0
- plain_admin-0.56.0/plain/admin/impersonate/requests.py +19 -0
- plain_admin-0.56.0/plain/admin/impersonate/settings.py +10 -0
- plain_admin-0.56.0/plain/admin/impersonate/urls.py +11 -0
- plain_admin-0.56.0/plain/admin/impersonate/views.py +24 -0
- plain_admin-0.56.0/plain/admin/middleware.py +10 -0
- plain_admin-0.56.0/plain/admin/templates/admin/base.html +262 -0
- plain_admin-0.56.0/plain/admin/templates/admin/cards/base.html +41 -0
- plain_admin-0.56.0/plain/admin/templates/admin/cards/card.html +17 -0
- plain_admin-0.56.0/plain/admin/templates/admin/cards/chart.html +31 -0
- plain_admin-0.56.0/plain/admin/templates/admin/cards/table.html +35 -0
- plain_admin-0.56.0/plain/admin/templates/admin/delete.html +16 -0
- plain_admin-0.56.0/plain/admin/templates/admin/detail.html +16 -0
- plain_admin-0.56.0/plain/admin/templates/admin/index.html +5 -0
- plain_admin-0.56.0/plain/admin/templates/admin/list.html +190 -0
- plain_admin-0.56.0/plain/admin/templates/admin/page.html +3 -0
- plain_admin-0.56.0/plain/admin/templates/admin/search.html +49 -0
- plain_admin-0.56.0/plain/admin/templates/admin/toolbar/button.html +21 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/UUID.html +1 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/bool.html +9 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/datetime.html +1 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/default.html +5 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/dict.html +1 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/img.html +4 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/list.html +1 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/model.html +15 -0
- plain_admin-0.56.0/plain/admin/templates/admin/values/queryset.html +7 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Checkbox.html +8 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/CheckboxField.html +10 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/FieldErrors.html +5 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Help.html +1 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Icon.html +3 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Input.html +8 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/InputField.html +8 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Label.html +4 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Select.html +10 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/SelectField.html +8 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Submit.html +6 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/Textarea.html +7 -0
- plain_admin-0.56.0/plain/admin/templates/elements/admin/TextareaField.html +8 -0
- plain_admin-0.56.0/plain/admin/templates.py +20 -0
- plain_admin-0.56.0/plain/admin/toolbar.py +24 -0
- plain_admin-0.56.0/plain/admin/urls.py +42 -0
- plain_admin-0.56.0/plain/admin/utils.py +14 -0
- plain_admin-0.56.0/plain/admin/views/__init__.py +41 -0
- plain_admin-0.56.0/plain/admin/views/base.py +128 -0
- plain_admin-0.56.0/plain/admin/views/models.py +251 -0
- plain_admin-0.56.0/plain/admin/views/objects.py +398 -0
- plain_admin-0.56.0/plain/admin/views/registry.py +192 -0
- plain_admin-0.56.0/plain/admin/views/types.py +13 -0
- plain_admin-0.56.0/plain/admin/views/viewsets.py +54 -0
- plain_admin-0.56.0/pyproject.toml +26 -0
- plain_admin-0.56.0/tests/app/settings.py +18 -0
- plain_admin-0.56.0/tests/app/urls.py +24 -0
- plain_admin-0.56.0/tests/app/users/migrations/0001_initial.py +21 -0
- plain_admin-0.56.0/tests/app/users/migrations/__init__.py +0 -0
- plain_admin-0.56.0/tests/app/users/models.py +12 -0
- plain_admin-0.56.0/tests/test_admin.py +24 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.venv
|
|
2
|
+
/.env
|
|
3
|
+
*.egg-info
|
|
4
|
+
*.py[co]
|
|
5
|
+
__pycache__
|
|
6
|
+
*.DS_Store
|
|
7
|
+
|
|
8
|
+
/*.code-workspace
|
|
9
|
+
|
|
10
|
+
# Test apps
|
|
11
|
+
plain*/tests/.plain
|
|
12
|
+
|
|
13
|
+
# Agent scratch files
|
|
14
|
+
/scratch
|
|
15
|
+
|
|
16
|
+
# Plain temp dirs
|
|
17
|
+
.plain
|
|
18
|
+
|
|
19
|
+
.vscode
|
|
20
|
+
/.claude
|
|
21
|
+
/.benchmarks
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023, Dropseed, LLC
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plain.admin
|
|
3
|
+
Version: 0.56.0
|
|
4
|
+
Summary: Manage your app with a backend interface.
|
|
5
|
+
Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Requires-Dist: plain-auth<1.0.0
|
|
10
|
+
Requires-Dist: plain-htmx<1.0.0
|
|
11
|
+
Requires-Dist: plain-tailwind<1.0.0
|
|
12
|
+
Requires-Dist: plain<1.0.0
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# plain.admin
|
|
16
|
+
|
|
17
|
+
**Manage your app with a backend interface.**
|
|
18
|
+
|
|
19
|
+
- [Overview](#overview)
|
|
20
|
+
- [Admin viewsets](#admin-viewsets)
|
|
21
|
+
- [Admin cards](#admin-cards)
|
|
22
|
+
- [Admin forms](#admin-forms)
|
|
23
|
+
- [List presets](#list-presets)
|
|
24
|
+
- [Toolbar](#toolbar)
|
|
25
|
+
- [Impersonate](#impersonate)
|
|
26
|
+
- [Installation](#installation)
|
|
27
|
+
|
|
28
|
+
## Overview
|
|
29
|
+
|
|
30
|
+
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.
|
|
31
|
+
|
|
32
|
+

|
|
33
|
+
|
|
34
|
+
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:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
# app/users/admin.py
|
|
38
|
+
from plain.admin.views import (
|
|
39
|
+
AdminModelDetailView,
|
|
40
|
+
AdminModelListView,
|
|
41
|
+
AdminModelUpdateView,
|
|
42
|
+
AdminViewset,
|
|
43
|
+
register_viewset,
|
|
44
|
+
)
|
|
45
|
+
from plain.models.forms import ModelForm
|
|
46
|
+
|
|
47
|
+
from .models import User
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class UserForm(ModelForm):
|
|
51
|
+
class Meta:
|
|
52
|
+
model = User
|
|
53
|
+
fields = ["email"]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@register_viewset
|
|
57
|
+
class UserAdmin(AdminViewset):
|
|
58
|
+
class ListView(AdminModelListView):
|
|
59
|
+
model = User
|
|
60
|
+
fields = [
|
|
61
|
+
"id",
|
|
62
|
+
"email",
|
|
63
|
+
"created_at__date",
|
|
64
|
+
]
|
|
65
|
+
queryset_order = ["-created_at"]
|
|
66
|
+
search_fields = [
|
|
67
|
+
"email",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
class DetailView(AdminModelDetailView):
|
|
71
|
+
model = User
|
|
72
|
+
|
|
73
|
+
class UpdateView(AdminModelUpdateView):
|
|
74
|
+
template_name = "admin/users/user_form.html"
|
|
75
|
+
model = User
|
|
76
|
+
form_class = UserForm
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Admin viewsets
|
|
80
|
+
|
|
81
|
+
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.
|
|
82
|
+
|
|
83
|
+
## Admin cards
|
|
84
|
+
|
|
85
|
+
TODO
|
|
86
|
+
|
|
87
|
+
## Admin forms
|
|
88
|
+
|
|
89
|
+
TODO
|
|
90
|
+
|
|
91
|
+
## List presets
|
|
92
|
+
|
|
93
|
+
On [`AdminListView`](./views/objects.py#AdminListView) and [`AdminModelListView`](./views/models.py#AdminModelListView), you can define different `presets` to build predefined views of your data. The preset choices will be shown in the UI, and you can use the current `self.preset` in your view logic.
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
# app/users/admin.py
|
|
97
|
+
from plain.admin.views import AdminModelListView, register_viewset
|
|
98
|
+
|
|
99
|
+
from .models import User
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@register_viewset
|
|
103
|
+
class UserAdmin(AdminViewset):
|
|
104
|
+
class ListView(AdminModelListView):
|
|
105
|
+
model = User
|
|
106
|
+
fields = [
|
|
107
|
+
"id",
|
|
108
|
+
"email",
|
|
109
|
+
"created_at__date",
|
|
110
|
+
]
|
|
111
|
+
presets = ["Users without email"]
|
|
112
|
+
|
|
113
|
+
def get_objects(self):
|
|
114
|
+
objects = super().get_objects()
|
|
115
|
+
|
|
116
|
+
if self.preset == "Users without email":
|
|
117
|
+
objects = objects.filter(email="")
|
|
118
|
+
|
|
119
|
+
return objects
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Toolbar
|
|
123
|
+
|
|
124
|
+
TODO
|
|
125
|
+
|
|
126
|
+
## Impersonate
|
|
127
|
+
|
|
128
|
+
TODO
|
|
129
|
+
|
|
130
|
+
## Installation
|
|
131
|
+
|
|
132
|
+
Install the `plain.admin` package from [PyPI](https://pypi.org/project/plain.admin/):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
uv add plain.admin
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
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:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
# app/settings.py
|
|
142
|
+
INSTALLED_PACKAGES = [
|
|
143
|
+
"plain.models",
|
|
144
|
+
"plain.tailwind",
|
|
145
|
+
"plain.auth",
|
|
146
|
+
"plain.sessions",
|
|
147
|
+
"plain.htmx",
|
|
148
|
+
"plain.admin",
|
|
149
|
+
"plain.elements",
|
|
150
|
+
# other packages...
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
AUTH_USER_MODEL = "users.User"
|
|
154
|
+
AUTH_LOGIN_URL = "login"
|
|
155
|
+
|
|
156
|
+
MIDDLEWARE = [
|
|
157
|
+
"plain.sessions.middleware.SessionMiddleware",
|
|
158
|
+
"plain.admin.AdminMiddleware",
|
|
159
|
+
]
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Your User model is expected to have an `is_admin` field (or attribute) for checking who has permission to access the admin.
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
# app/users/models.py
|
|
166
|
+
from plain import models
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@models.register_model
|
|
170
|
+
class User(models.Model):
|
|
171
|
+
is_admin = models.BooleanField(default=False)
|
|
172
|
+
# other fields...
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
To make the admin accessible, add the [`AdminRouter`](./urls.py#AdminRouter) to your root URLs.
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
# app/urls.py
|
|
179
|
+
from plain.admin.urls import AdminRouter
|
|
180
|
+
from plain.urls import Router, include, path
|
|
181
|
+
|
|
182
|
+
from . import views
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class AppRouter(Router):
|
|
186
|
+
namespace = ""
|
|
187
|
+
urls = [
|
|
188
|
+
include("admin/", AdminRouter),
|
|
189
|
+
path("login/", views.LoginView, name="login"),
|
|
190
|
+
path("logout/", LogoutView, name="logout"),
|
|
191
|
+
# other urls...
|
|
192
|
+
]
|
|
193
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
plain/admin/README.md
|