fastadmin 0.1.41__tar.gz → 0.2.2__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.
- {fastadmin-0.1.41 → fastadmin-0.2.2}/PKG-INFO +23 -23
- {fastadmin-0.1.41 → fastadmin-0.2.2}/README.md +20 -19
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/django/app/api.py +2 -2
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/fastapi/api.py +2 -2
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/flask/api.py +14 -14
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/flask/app.py +2 -2
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/helpers.py +13 -20
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/service.py +5 -5
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/base.py +19 -3
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/decorators.py +1 -1
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/helpers.py +1 -1
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/orms/ponyorm.py +4 -5
- fastadmin-0.2.2/fastadmin/static/index.html +19 -0
- fastadmin-0.2.2/fastadmin/static/index.min.css +6 -0
- fastadmin-0.2.2/fastadmin/static/index.min.js +755 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/templates/index.html +2 -2
- {fastadmin-0.1.41 → fastadmin-0.2.2}/pyproject.toml +12 -12
- fastadmin-0.1.41/fastadmin/static/css/main.min.css +0 -7
- fastadmin-0.1.41/fastadmin/static/js/27.07bc2567.chunk.js +0 -1
- fastadmin-0.1.41/fastadmin/static/js/main.min.js +0 -2
- {fastadmin-0.1.41 → fastadmin-0.2.2}/LICENSE +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/exceptions.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/django/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/django/app/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/django/app/urls.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/django/app/views.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/fastapi/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/fastapi/app.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/fastapi/views.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/flask/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/frameworks/flask/views.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/api/schemas.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/orms/__init__.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/orms/django.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/orms/sqlalchemy.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/orms/tortoise.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/models/schemas.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/settings.py +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/static/images/favicon.png +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/static/images/header-logo.svg +0 -0
- {fastadmin-0.1.41 → fastadmin-0.2.2}/fastadmin/static/images/sign-in-logo.svg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fastadmin
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.2.2
|
4
4
|
Summary:
|
5
5
|
Home-page: https://github.com/vsdudakov/fastadmin
|
6
6
|
License: MIT
|
@@ -17,6 +17,7 @@ Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
18
18
|
Classifier: Programming Language :: Python :: 3.10
|
19
19
|
Classifier: Programming Language :: Python :: 3.11
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
20
21
|
Classifier: Topic :: Software Development :: Documentation
|
21
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
22
23
|
Classifier: Topic :: Software Development :: Widget Sets
|
@@ -26,14 +27,13 @@ Provides-Extra: flask
|
|
26
27
|
Provides-Extra: pony
|
27
28
|
Provides-Extra: sqlalchemy
|
28
29
|
Provides-Extra: tortoise-orm
|
29
|
-
Requires-Dist: asgiref (
|
30
|
+
Requires-Dist: asgiref (==3.6.0)
|
30
31
|
Requires-Dist: django (==4.*) ; extra == "django"
|
31
32
|
Requires-Dist: fastapi (==0.*) ; extra == "fastapi"
|
32
33
|
Requires-Dist: flask (==2.*) ; extra == "flask"
|
33
|
-
Requires-Dist:
|
34
|
+
Requires-Dist: greenlet (>=3.0.3,<4.0.0)
|
34
35
|
Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
|
35
36
|
Requires-Dist: pony (==0.*) ; extra == "pony"
|
36
|
-
Requires-Dist: pydantic (>=1.10.7,<2.0.0)
|
37
37
|
Requires-Dist: pyjwt (>=2.6.0,<3.0.0)
|
38
38
|
Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
|
39
39
|
Requires-Dist: sqlalchemy (==2.*) ; extra == "sqlalchemy"
|
@@ -43,11 +43,12 @@ Description-Content-Type: text/markdown
|
|
43
43
|
|
44
44
|
## Admin Dashboard App for FastAPI/Flask/Django
|
45
45
|
|
46
|
-
[](https://github.com/vsdudakov/fastadmin/workflows/CI/badge.svg?branch=main)
|
47
46
|
[](https://codecov.io/gh/vsdudakov/fastadmin)
|
48
47
|
[](https://github.com/vsdudakov/fastadmin/blob/master/LICENSE)
|
49
48
|
[](https://pypi.org/project/fastadmin/)
|
50
49
|
[](https://www.python.org/downloads/release/python-3100/)
|
50
|
+
[](https://www.python.org/downloads/release/python-3110/)
|
51
|
+
[](https://www.python.org/downloads/release/python-3120/)
|
51
52
|
|
52
53
|
## Screenshots
|
53
54
|
|
@@ -65,7 +66,7 @@ Description-Content-Type: text/markdown
|
|
65
66
|
|
66
67
|
## Introduction
|
67
68
|
|
68
|
-
|
69
|
+
|
69
70
|
<a href='https://github.com/vsdudakov/fastadmin' target='_blank'>FastAdmin</a> is an easy-to-use Admin Dashboard App for FastAPI/Django/Flask inspired by Django Admin.
|
70
71
|
|
71
72
|
|
@@ -81,7 +82,7 @@ Description-Content-Type: text/markdown
|
|
81
82
|
|
82
83
|
|
83
84
|
|
84
|
-
|
85
|
+
|
85
86
|
FastAdmin was built with relations in mind and admiration for the excellent and popular Django Admin. It's engraved in its design that you may configure your admin dashboard for FastAPI/Django/Flask easiest way.
|
86
87
|
|
87
88
|
|
@@ -97,7 +98,7 @@ FastAdmin was built with relations in mind and admiration for the excellent and
|
|
97
98
|
|
98
99
|
|
99
100
|
|
100
|
-
|
101
|
+
|
101
102
|
FastAdmin is designed to be minimalistic, functional and yet familiar.
|
102
103
|
|
103
104
|
|
@@ -119,7 +120,7 @@ FastAdmin is designed to be minimalistic, functional and yet familiar.
|
|
119
120
|
|
120
121
|
## Getting Started
|
121
122
|
|
122
|
-
|
123
|
+
|
123
124
|
|
124
125
|
|
125
126
|
|
@@ -139,7 +140,7 @@ If you have any questions that are beyond the scope of the documentation, Please
|
|
139
140
|
|
140
141
|
### Installation
|
141
142
|
|
142
|
-
|
143
|
+
|
143
144
|
|
144
145
|
|
145
146
|
Follow the steps below to setup FastAdmin:
|
@@ -155,7 +156,7 @@ Follow the steps below to setup FastAdmin:
|
|
155
156
|
|
156
157
|
|
157
158
|
|
158
|
-
|
159
|
+
|
159
160
|
Install the package using pip:
|
160
161
|
|
161
162
|
|
@@ -171,7 +172,7 @@ Install the package using pip:
|
|
171
172
|
|
172
173
|
|
173
174
|
|
174
|
-
|
175
|
+
|
175
176
|
|
176
177
|
|
177
178
|
|
@@ -187,7 +188,7 @@ Note: For zsh and macos use: <code>pip install fastadmin[fastapi,django]</code>
|
|
187
188
|
|
188
189
|
|
189
190
|
|
190
|
-
|
191
|
+
|
191
192
|
|
192
193
|
|
193
194
|
|
@@ -213,7 +214,7 @@ pip install fastadmin[flask,sqlalchemy] # for flask with sqlalchemy
|
|
213
214
|
|
214
215
|
|
215
216
|
|
216
|
-
|
217
|
+
|
217
218
|
Install the package using poetry:
|
218
219
|
|
219
220
|
|
@@ -229,7 +230,7 @@ Install the package using poetry:
|
|
229
230
|
|
230
231
|
|
231
232
|
|
232
|
-
|
233
|
+
|
233
234
|
|
234
235
|
|
235
236
|
|
@@ -255,7 +256,7 @@ poetry add 'fastadmin[flask,sqlalchemy]' # for flask with sqlalchemy
|
|
255
256
|
|
256
257
|
|
257
258
|
|
258
|
-
|
259
|
+
|
259
260
|
Configure required settings using virtual environment variables:
|
260
261
|
|
261
262
|
|
@@ -271,7 +272,7 @@ Configure required settings using virtual environment variables:
|
|
271
272
|
|
272
273
|
|
273
274
|
|
274
|
-
|
275
|
+
|
275
276
|
|
276
277
|
|
277
278
|
|
@@ -287,7 +288,7 @@ Note: You can add these variables to .env and use python-dotenv to load them. Se
|
|
287
288
|
|
288
289
|
|
289
290
|
|
290
|
-
|
291
|
+
|
291
292
|
|
292
293
|
|
293
294
|
|
@@ -312,7 +313,7 @@ export ADMIN_SECRET_KEY=secret_key
|
|
312
313
|
|
313
314
|
### Quick Tutorial
|
314
315
|
|
315
|
-
|
316
|
+
|
316
317
|
|
317
318
|
|
318
319
|
Setup FastAdmin for a framework
|
@@ -328,7 +329,7 @@ Setup FastAdmin for a framework
|
|
328
329
|
|
329
330
|
|
330
331
|
|
331
|
-
|
332
|
+
|
332
333
|
|
333
334
|
|
334
335
|
|
@@ -432,7 +433,7 @@ app.register_blueprint(admin_app, url_prefix="/admin")
|
|
432
433
|
|
433
434
|
|
434
435
|
|
435
|
-
|
436
|
+
|
436
437
|
|
437
438
|
|
438
439
|
Register ORM models
|
@@ -448,7 +449,7 @@ Register ORM models
|
|
448
449
|
|
449
450
|
|
450
451
|
|
451
|
-
|
452
|
+
|
452
453
|
|
453
454
|
|
454
455
|
|
@@ -722,4 +723,3 @@ See full documentation [here](https://vsdudakov.github.io/fastadmin).
|
|
722
723
|
|
723
724
|
## License
|
724
725
|
This project is licensed under the MIT License - see the [LICENSE](https://github.com/vsdudakov/fastadmin/blob/main/LICENSE) file for details.
|
725
|
-
|
@@ -1,10 +1,11 @@
|
|
1
1
|
## Admin Dashboard App for FastAPI/Flask/Django
|
2
2
|
|
3
|
-
[](https://github.com/vsdudakov/fastadmin/workflows/CI/badge.svg?branch=main)
|
4
3
|
[](https://codecov.io/gh/vsdudakov/fastadmin)
|
5
4
|
[](https://github.com/vsdudakov/fastadmin/blob/master/LICENSE)
|
6
5
|
[](https://pypi.org/project/fastadmin/)
|
7
6
|
[](https://www.python.org/downloads/release/python-3100/)
|
7
|
+
[](https://www.python.org/downloads/release/python-3110/)
|
8
|
+
[](https://www.python.org/downloads/release/python-3120/)
|
8
9
|
|
9
10
|
## Screenshots
|
10
11
|
|
@@ -22,7 +23,7 @@
|
|
22
23
|
|
23
24
|
## Introduction
|
24
25
|
|
25
|
-
|
26
|
+
|
26
27
|
<a href='https://github.com/vsdudakov/fastadmin' target='_blank'>FastAdmin</a> is an easy-to-use Admin Dashboard App for FastAPI/Django/Flask inspired by Django Admin.
|
27
28
|
|
28
29
|
|
@@ -38,7 +39,7 @@
|
|
38
39
|
|
39
40
|
|
40
41
|
|
41
|
-
|
42
|
+
|
42
43
|
FastAdmin was built with relations in mind and admiration for the excellent and popular Django Admin. It's engraved in its design that you may configure your admin dashboard for FastAPI/Django/Flask easiest way.
|
43
44
|
|
44
45
|
|
@@ -54,7 +55,7 @@ FastAdmin was built with relations in mind and admiration for the excellent and
|
|
54
55
|
|
55
56
|
|
56
57
|
|
57
|
-
|
58
|
+
|
58
59
|
FastAdmin is designed to be minimalistic, functional and yet familiar.
|
59
60
|
|
60
61
|
|
@@ -76,7 +77,7 @@ FastAdmin is designed to be minimalistic, functional and yet familiar.
|
|
76
77
|
|
77
78
|
## Getting Started
|
78
79
|
|
79
|
-
|
80
|
+
|
80
81
|
|
81
82
|
|
82
83
|
|
@@ -96,7 +97,7 @@ If you have any questions that are beyond the scope of the documentation, Please
|
|
96
97
|
|
97
98
|
### Installation
|
98
99
|
|
99
|
-
|
100
|
+
|
100
101
|
|
101
102
|
|
102
103
|
Follow the steps below to setup FastAdmin:
|
@@ -112,7 +113,7 @@ Follow the steps below to setup FastAdmin:
|
|
112
113
|
|
113
114
|
|
114
115
|
|
115
|
-
|
116
|
+
|
116
117
|
Install the package using pip:
|
117
118
|
|
118
119
|
|
@@ -128,7 +129,7 @@ Install the package using pip:
|
|
128
129
|
|
129
130
|
|
130
131
|
|
131
|
-
|
132
|
+
|
132
133
|
|
133
134
|
|
134
135
|
|
@@ -144,7 +145,7 @@ Note: For zsh and macos use: <code>pip install fastadmin[fastapi,django]</code>
|
|
144
145
|
|
145
146
|
|
146
147
|
|
147
|
-
|
148
|
+
|
148
149
|
|
149
150
|
|
150
151
|
|
@@ -170,7 +171,7 @@ pip install fastadmin[flask,sqlalchemy] # for flask with sqlalchemy
|
|
170
171
|
|
171
172
|
|
172
173
|
|
173
|
-
|
174
|
+
|
174
175
|
Install the package using poetry:
|
175
176
|
|
176
177
|
|
@@ -186,7 +187,7 @@ Install the package using poetry:
|
|
186
187
|
|
187
188
|
|
188
189
|
|
189
|
-
|
190
|
+
|
190
191
|
|
191
192
|
|
192
193
|
|
@@ -212,7 +213,7 @@ poetry add 'fastadmin[flask,sqlalchemy]' # for flask with sqlalchemy
|
|
212
213
|
|
213
214
|
|
214
215
|
|
215
|
-
|
216
|
+
|
216
217
|
Configure required settings using virtual environment variables:
|
217
218
|
|
218
219
|
|
@@ -228,7 +229,7 @@ Configure required settings using virtual environment variables:
|
|
228
229
|
|
229
230
|
|
230
231
|
|
231
|
-
|
232
|
+
|
232
233
|
|
233
234
|
|
234
235
|
|
@@ -244,7 +245,7 @@ Note: You can add these variables to .env and use python-dotenv to load them. Se
|
|
244
245
|
|
245
246
|
|
246
247
|
|
247
|
-
|
248
|
+
|
248
249
|
|
249
250
|
|
250
251
|
|
@@ -269,7 +270,7 @@ export ADMIN_SECRET_KEY=secret_key
|
|
269
270
|
|
270
271
|
### Quick Tutorial
|
271
272
|
|
272
|
-
|
273
|
+
|
273
274
|
|
274
275
|
|
275
276
|
Setup FastAdmin for a framework
|
@@ -285,7 +286,7 @@ Setup FastAdmin for a framework
|
|
285
286
|
|
286
287
|
|
287
288
|
|
288
|
-
|
289
|
+
|
289
290
|
|
290
291
|
|
291
292
|
|
@@ -389,7 +390,7 @@ app.register_blueprint(admin_app, url_prefix="/admin")
|
|
389
390
|
|
390
391
|
|
391
392
|
|
392
|
-
|
393
|
+
|
393
394
|
|
394
395
|
|
395
396
|
Register ORM models
|
@@ -405,7 +406,7 @@ Register ORM models
|
|
405
406
|
|
406
407
|
|
407
408
|
|
408
|
-
|
409
|
+
|
409
410
|
|
410
411
|
|
411
412
|
|
@@ -678,4 +679,4 @@ class UserAdmin(PonyORMModelAdmin):
|
|
678
679
|
See full documentation [here](https://vsdudakov.github.io/fastadmin).
|
679
680
|
|
680
681
|
## License
|
681
|
-
This project is licensed under the MIT License - see the [LICENSE](https://github.com/vsdudakov/fastadmin/blob/main/LICENSE) file for details.
|
682
|
+
This project is licensed under the MIT License - see the [LICENSE](https://github.com/vsdudakov/fastadmin/blob/main/LICENSE) file for details.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
from dataclasses import asdict
|
4
|
-
from datetime import datetime
|
4
|
+
from datetime import datetime, time
|
5
5
|
from functools import wraps
|
6
6
|
from uuid import UUID
|
7
7
|
|
@@ -23,7 +23,7 @@ api_service = ApiService()
|
|
23
23
|
|
24
24
|
class JsonEncoder(DjangoJSONEncoder):
|
25
25
|
def default(self, o):
|
26
|
-
if isinstance(o, datetime):
|
26
|
+
if isinstance(o, datetime | time):
|
27
27
|
return o.isoformat()
|
28
28
|
if isinstance(o, UUID):
|
29
29
|
return str(o)
|
@@ -117,7 +117,7 @@ async def list_objs(
|
|
117
117
|
request: Request,
|
118
118
|
model: str,
|
119
119
|
search: str | None = None,
|
120
|
-
sort_by: str = None,
|
120
|
+
sort_by: str | None = None,
|
121
121
|
offset: int | None = 0,
|
122
122
|
limit: int | None = 10,
|
123
123
|
):
|
@@ -238,7 +238,7 @@ async def export(
|
|
238
238
|
model: str,
|
239
239
|
payload: ExportInputSchema,
|
240
240
|
search: str | None = None,
|
241
|
-
sort_by: str = None,
|
241
|
+
sort_by: str | None = None,
|
242
242
|
):
|
243
243
|
"""This method is used to export a list of objects.
|
244
244
|
|
@@ -37,7 +37,7 @@ async def sign_in() -> Response:
|
|
37
37
|
except AdminApiException as e:
|
38
38
|
http_exception = HTTPException(e.detail)
|
39
39
|
http_exception.code = e.status_code
|
40
|
-
raise http_exception
|
40
|
+
raise http_exception from e
|
41
41
|
|
42
42
|
|
43
43
|
@api_router.route("/sign-out", methods=["POST"])
|
@@ -57,7 +57,7 @@ async def sign_out() -> Response:
|
|
57
57
|
except AdminApiException as e:
|
58
58
|
http_exception = HTTPException(e.detail)
|
59
59
|
http_exception.code = e.status_code
|
60
|
-
raise http_exception
|
60
|
+
raise http_exception from e
|
61
61
|
|
62
62
|
|
63
63
|
@api_router.route("/me", methods=["GET"])
|
@@ -79,7 +79,7 @@ async def me() -> dict:
|
|
79
79
|
except AdminApiException as e:
|
80
80
|
http_exception = HTTPException(e.detail)
|
81
81
|
http_exception.code = e.status_code
|
82
|
-
raise http_exception
|
82
|
+
raise http_exception from e
|
83
83
|
|
84
84
|
|
85
85
|
@api_router.route("/dashboard-widget/<string:model>", methods=["GET"])
|
@@ -109,7 +109,7 @@ async def dashboard_widget(model: str) -> dict:
|
|
109
109
|
except AdminApiException as e:
|
110
110
|
http_exception = HTTPException(e.detail)
|
111
111
|
http_exception.code = e.status_code
|
112
|
-
raise http_exception
|
112
|
+
raise http_exception from e
|
113
113
|
|
114
114
|
|
115
115
|
@api_router.route("/list/<string:model>", methods=["GET"])
|
@@ -143,14 +143,14 @@ async def list_objs(model: str) -> dict:
|
|
143
143
|
"total": total,
|
144
144
|
"results": objs,
|
145
145
|
}
|
146
|
-
except ValueError:
|
146
|
+
except ValueError as e:
|
147
147
|
http_exception = HTTPException("Invalid format of get parameters")
|
148
148
|
http_exception.code = 422
|
149
|
-
raise http_exception
|
149
|
+
raise http_exception from e
|
150
150
|
except AdminApiException as e:
|
151
151
|
http_exception = HTTPException(e.detail)
|
152
152
|
http_exception.code = e.status_code
|
153
|
-
raise http_exception
|
153
|
+
raise http_exception from e
|
154
154
|
|
155
155
|
|
156
156
|
@api_router.route("/retrieve/<string:model>/<string:id>", methods=["GET"])
|
@@ -174,7 +174,7 @@ async def get(model: str, id: UUID | int) -> dict:
|
|
174
174
|
except AdminApiException as e:
|
175
175
|
http_exception = HTTPException(e.detail)
|
176
176
|
http_exception.code = e.status_code
|
177
|
-
raise http_exception
|
177
|
+
raise http_exception from e
|
178
178
|
|
179
179
|
|
180
180
|
@api_router.route("/add/<string:model>", methods=["POST"])
|
@@ -195,7 +195,7 @@ async def add(model: str) -> dict:
|
|
195
195
|
except AdminApiException as e:
|
196
196
|
http_exception = HTTPException(e.detail)
|
197
197
|
http_exception.code = e.status_code
|
198
|
-
raise http_exception
|
198
|
+
raise http_exception from e
|
199
199
|
|
200
200
|
|
201
201
|
@api_router.route("/change-password/<string:id>", methods=["PATCH"]) # type: ignore [type-var]
|
@@ -221,7 +221,7 @@ async def change_password(id: UUID | int) -> UUID | int:
|
|
221
221
|
except AdminApiException as e:
|
222
222
|
http_exception = HTTPException(e.detail)
|
223
223
|
http_exception.code = e.status_code
|
224
|
-
raise http_exception
|
224
|
+
raise http_exception from e
|
225
225
|
|
226
226
|
|
227
227
|
@api_router.route("/change/<string:model>/<string:id>", methods=["PATCH"])
|
@@ -248,7 +248,7 @@ async def change(model: str, id: UUID | int) -> dict:
|
|
248
248
|
except AdminApiException as e:
|
249
249
|
http_exception = HTTPException(e.detail)
|
250
250
|
http_exception.code = e.status_code
|
251
|
-
raise http_exception
|
251
|
+
raise http_exception from e
|
252
252
|
|
253
253
|
|
254
254
|
@api_router.route("/export/<string:model>", methods=["POST"])
|
@@ -282,7 +282,7 @@ async def export(model: str) -> Response:
|
|
282
282
|
except AdminApiException as e:
|
283
283
|
http_exception = HTTPException(e.detail)
|
284
284
|
http_exception.code = e.status_code
|
285
|
-
raise http_exception
|
285
|
+
raise http_exception from e
|
286
286
|
|
287
287
|
|
288
288
|
@api_router.route("/delete/<string:model>/<string:id>", methods=["DELETE"]) # type: ignore [type-var]
|
@@ -309,7 +309,7 @@ async def delete(
|
|
309
309
|
except AdminApiException as e:
|
310
310
|
http_exception = HTTPException(e.detail)
|
311
311
|
http_exception.code = e.status_code
|
312
|
-
raise http_exception
|
312
|
+
raise http_exception from e
|
313
313
|
|
314
314
|
|
315
315
|
@api_router.route("/action/<string:model>/<string:action>", methods=["POST"])
|
@@ -337,7 +337,7 @@ async def action(
|
|
337
337
|
except AdminApiException as e:
|
338
338
|
http_exception = HTTPException(e.detail)
|
339
339
|
http_exception.code = e.status_code
|
340
|
-
raise http_exception
|
340
|
+
raise http_exception from e
|
341
341
|
|
342
342
|
|
343
343
|
@api_router.route("/configuration", methods=["GET"])
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import logging
|
2
|
-
from datetime import date
|
2
|
+
from datetime import date, time
|
3
3
|
|
4
4
|
from flask import Blueprint
|
5
5
|
from flask.json.provider import DefaultJSONProvider
|
@@ -14,7 +14,7 @@ logger = logging.getLogger(__name__)
|
|
14
14
|
|
15
15
|
class JSONProvider(DefaultJSONProvider):
|
16
16
|
def default(self, o):
|
17
|
-
if isinstance(o, date):
|
17
|
+
if isinstance(o, date | time):
|
18
18
|
return o.isoformat()
|
19
19
|
return super().default(o)
|
20
20
|
|
@@ -30,12 +30,11 @@ def sanitize_filter_key(key: str, fields: list[ModelFieldWidgetSchema]) -> tuple
|
|
30
30
|
:return: A tuple of sanitized key and condition.
|
31
31
|
"""
|
32
32
|
if "__" not in key:
|
33
|
-
key
|
34
|
-
field_name = key.
|
35
|
-
condition = key.split("__", 1)[1]
|
33
|
+
key += "__exact"
|
34
|
+
field_name, _, condition = key.partition("__")
|
36
35
|
field: ModelFieldWidgetSchema | None = next((field for field in fields if field.name == field_name), None)
|
37
36
|
if field and field.filter_widget_props.get("parentModel") and not field.is_m2m:
|
38
|
-
field_name
|
37
|
+
field_name += "_id"
|
39
38
|
return field_name, condition
|
40
39
|
|
41
40
|
|
@@ -52,32 +51,26 @@ def is_valid_uuid(uuid_to_test: str) -> bool:
|
|
52
51
|
return str(uuid_obj) == uuid_to_test
|
53
52
|
|
54
53
|
|
55
|
-
def is_digit(digit_to_test: str) -> bool:
|
56
|
-
"""Check if digit_to_test is a digit.
|
57
|
-
|
58
|
-
:param digit_to_test: A digit to test.
|
59
|
-
:return: True if digit_to_test is a digit, False otherwise.
|
60
|
-
"""
|
61
|
-
try:
|
62
|
-
int(digit_to_test)
|
63
|
-
except ValueError:
|
64
|
-
return False
|
65
|
-
return True
|
66
|
-
|
67
|
-
|
68
54
|
def is_valid_id(id: UUID | int) -> bool:
|
69
55
|
"""Check if id is a valid id.
|
70
56
|
|
71
57
|
:param id: An id to test.
|
72
58
|
:return: True if id is a valid id, False otherwise.
|
73
59
|
"""
|
74
|
-
|
60
|
+
if is_valid_uuid(str(id)):
|
61
|
+
return True
|
62
|
+
try:
|
63
|
+
int(id)
|
64
|
+
return True
|
65
|
+
except ValueError:
|
66
|
+
pass
|
67
|
+
return False
|
75
68
|
|
76
69
|
|
77
70
|
def is_valid_base64(value: str) -> bool:
|
78
|
-
"""Check if
|
71
|
+
"""Check if a string is a valid base64.
|
79
72
|
|
80
|
-
:param
|
73
|
+
:param value: A string to test.
|
81
74
|
:return: True if s is a valid base64, False otherwise.
|
82
75
|
"""
|
83
76
|
try:
|
@@ -107,7 +107,7 @@ class ApiService:
|
|
107
107
|
if inspect.iscoroutinefunction(admin_model.authenticate):
|
108
108
|
authenticate_fn = admin_model.authenticate
|
109
109
|
else:
|
110
|
-
authenticate_fn = sync_to_async(admin_model.authenticate)
|
110
|
+
authenticate_fn = sync_to_async(admin_model.authenticate) # type: ignore [arg-type]
|
111
111
|
|
112
112
|
user_id = await authenticate_fn(payload.username, payload.password)
|
113
113
|
|
@@ -162,7 +162,7 @@ class ApiService:
|
|
162
162
|
if inspect.iscoroutinefunction(dashboard_widget_model.get_data):
|
163
163
|
get_data = dashboard_widget_model.get_data
|
164
164
|
else:
|
165
|
-
get_data = sync_to_async(dashboard_widget_model.get_data)
|
165
|
+
get_data = sync_to_async(dashboard_widget_model.get_data) # type: ignore [arg-type]
|
166
166
|
data = await get_data(
|
167
167
|
min_x_field=query_params.min_x_field,
|
168
168
|
max_x_field=query_params.max_x_field,
|
@@ -178,7 +178,7 @@ class ApiService:
|
|
178
178
|
model: str,
|
179
179
|
search: str | None = None,
|
180
180
|
sort_by: str | None = None,
|
181
|
-
filters: dict = None,
|
181
|
+
filters: dict | None = None,
|
182
182
|
offset: int | None = 0,
|
183
183
|
limit: int | None = 10,
|
184
184
|
) -> tuple[list[dict], int]:
|
@@ -302,7 +302,7 @@ class ApiService:
|
|
302
302
|
if inspect.iscoroutinefunction(admin_model.change_password):
|
303
303
|
change_password_fn = admin_model.change_password
|
304
304
|
else:
|
305
|
-
change_password_fn = sync_to_async(admin_model.change_password)
|
305
|
+
change_password_fn = sync_to_async(admin_model.change_password) # type: ignore [arg-type]
|
306
306
|
await change_password_fn(id, payload.password)
|
307
307
|
|
308
308
|
async def change(
|
@@ -332,7 +332,7 @@ class ApiService:
|
|
332
332
|
payload: ExportInputSchema,
|
333
333
|
search: str | None = None,
|
334
334
|
sort_by: str | None = None,
|
335
|
-
filters: dict = None,
|
335
|
+
filters: dict | None = None,
|
336
336
|
) -> tuple[str, str, StringIO | BytesIO | None]:
|
337
337
|
current_user_id = await get_user_id_from_session_id(session_id)
|
338
338
|
if not current_user_id:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import csv
|
2
|
+
import datetime
|
2
3
|
import inspect
|
3
4
|
import json
|
4
5
|
from collections.abc import Sequence
|
@@ -87,7 +88,7 @@ class BaseModelAdmin:
|
|
87
88
|
# formfield_overrides = {
|
88
89
|
# "description": (WidgetType.RichTextArea, {})
|
89
90
|
# }
|
90
|
-
formfield_overrides: dict[str, tuple[WidgetType, dict]] = {}
|
91
|
+
formfield_overrides: dict[str, tuple[WidgetType, dict]] = {} # noqa: RUF012
|
91
92
|
|
92
93
|
# Set list_display to control which fields are displayed on the list page of the admin.
|
93
94
|
# If you don't set list_display, the admin site will display a single column that displays the __str__() representation of each object
|
@@ -104,7 +105,7 @@ class BaseModelAdmin:
|
|
104
105
|
# list_display_widths = {
|
105
106
|
# "id": "100px",
|
106
107
|
# }
|
107
|
-
list_display_widths: dict[str, str] = {}
|
108
|
+
list_display_widths: dict[str, str] = {} # noqa: RUF012
|
108
109
|
|
109
110
|
# Set list_filter to activate filters in the tabel columns of the list page of the admin.
|
110
111
|
# Example of usage: list_filter = ("is_superuser", "is_active", "created_at")
|
@@ -383,6 +384,17 @@ class BaseModelAdmin:
|
|
383
384
|
|
384
385
|
return obj_dict
|
385
386
|
|
387
|
+
def deserialize_value(self, field: ModelFieldWidgetSchema, value: Any) -> Any:
|
388
|
+
if not value:
|
389
|
+
return value
|
390
|
+
match field.form_widget_type:
|
391
|
+
case WidgetType.TimePicker:
|
392
|
+
return datetime.datetime.fromisoformat(value).time()
|
393
|
+
case WidgetType.DatePicker | WidgetType.DateTimePicker:
|
394
|
+
return datetime.datetime.fromisoformat(value)
|
395
|
+
case _:
|
396
|
+
return value
|
397
|
+
|
386
398
|
async def get_list(
|
387
399
|
self,
|
388
400
|
offset: int | None = None,
|
@@ -434,7 +446,11 @@ class BaseModelAdmin:
|
|
434
446
|
m2m_fields = self.get_model_fields_with_widget_types(with_m2m=True)
|
435
447
|
upload_fields = self.get_model_fields_with_widget_types(with_upload=True)
|
436
448
|
|
437
|
-
fields_payload = {
|
449
|
+
fields_payload = {
|
450
|
+
field.column_name: self.deserialize_value(field, payload[field.name])
|
451
|
+
for field in fields
|
452
|
+
if field.name in payload
|
453
|
+
}
|
438
454
|
obj = await self.orm_save_obj(id, fields_payload)
|
439
455
|
if not obj:
|
440
456
|
return None
|