sqladmin 0.8.0__py3-none-any.whl → 0.10.0__py3-none-any.whl
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.
- sqladmin/__init__.py +1 -1
- sqladmin/_queries.py +18 -9
- sqladmin/_types.py +1 -1
- sqladmin/_validators.py +24 -0
- sqladmin/ajax.py +1 -1
- sqladmin/application.py +46 -7
- sqladmin/authentication.py +10 -6
- sqladmin/fields.py +52 -5
- sqladmin/forms.py +61 -16
- sqladmin/helpers.py +99 -16
- sqladmin/models.py +119 -118
- sqladmin/statics/js/main.js +14 -0
- sqladmin/templates/create.html +1 -1
- sqladmin/templates/details.html +6 -6
- sqladmin/templates/edit.html +1 -1
- sqladmin/templates/list.html +10 -10
- sqladmin/widgets.py +30 -1
- {sqladmin-0.8.0.dist-info → sqladmin-0.10.0.dist-info}/METADATA +9 -3
- {sqladmin-0.8.0.dist-info → sqladmin-0.10.0.dist-info}/RECORD +21 -21
- {sqladmin-0.8.0.dist-info → sqladmin-0.10.0.dist-info}/WHEEL +1 -1
- {sqladmin-0.8.0.dist-info → sqladmin-0.10.0.dist-info}/licenses/LICENSE.md +0 -0
sqladmin/templates/details.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="col-12">
|
|
4
4
|
<div class="card">
|
|
5
5
|
<div class="card-header">
|
|
6
|
-
<h3 class="card-title">{{ model_view.pk_column.name }}: {{ model_view.
|
|
6
|
+
<h3 class="card-title">{{ model_view.pk_column.name }}: {{ model_view.get_prop_value(model, model_view.pk_column) }}</h3>
|
|
7
7
|
</div>
|
|
8
8
|
<div class="card-body border-bottom py-3">
|
|
9
9
|
<div class="table-responsive">
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
</tr>
|
|
16
16
|
</thead>
|
|
17
17
|
<tbody>
|
|
18
|
-
{% for name,
|
|
18
|
+
{% for name, prop in model_view._details_props %}
|
|
19
19
|
<tr>
|
|
20
20
|
<td>{{ name }}</td>
|
|
21
|
-
{% set value, formatted_value = model_view.get_detail_value(model,
|
|
22
|
-
{% if
|
|
21
|
+
{% set value, formatted_value = model_view.get_detail_value(model, prop) %}
|
|
22
|
+
{% if prop in model_view._relation_props %}
|
|
23
23
|
{% if is_list( value ) %}
|
|
24
24
|
<td>
|
|
25
25
|
{% for elem, formatted_elem in zip(value, formatted_value) %}
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
{% endfor %}
|
|
28
28
|
</td>
|
|
29
29
|
{% else %}
|
|
30
|
-
<td><a href="{{ model_view.
|
|
30
|
+
<td><a href="{{ model_view._url_for_details_with_prop(request, model, prop) }}">{{ formatted_value }}</a></td>
|
|
31
31
|
{% endif %}
|
|
32
32
|
{% else %}
|
|
33
33
|
<td>{{ formatted_value }}</td>
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
</div>
|
|
47
47
|
{% if model_view.can_delete %}
|
|
48
48
|
<div class="col-md-1">
|
|
49
|
-
<a href="#" data-name="{{ model_view.name }}" data-pk="{{ model_view.
|
|
49
|
+
<a href="#" data-name="{{ model_view.name }}" data-pk="{{ model_view.get_prop_value(model, model_view.pk_column) }}" data-url="{{ model_view._url_for_delete(request, model) }}" data-bs-toggle="modal" data-bs-target="#modal-delete" class="btn btn-danger">
|
|
50
50
|
Delete
|
|
51
51
|
</a>
|
|
52
52
|
</div>
|
sqladmin/templates/edit.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<h3 class="card-title">Edit {{ model_view.name }}</h3>
|
|
7
7
|
</div>
|
|
8
8
|
<div class="card-body border-bottom py-3">
|
|
9
|
-
<form action="{{ request.url }}" method="POST">
|
|
9
|
+
<form action="{{ request.url }}" method="POST" enctype="multipart/form-data">
|
|
10
10
|
<fieldset class="form-fieldset">
|
|
11
11
|
{% for field in form %}
|
|
12
12
|
<div class="mb-3 form-group row">
|
sqladmin/templates/list.html
CHANGED
|
@@ -63,15 +63,15 @@
|
|
|
63
63
|
<tr>
|
|
64
64
|
<th class="w-1"><input class="form-check-input m-0 align-middle" type="checkbox" aria-label="Select all" id="select-all"></th>
|
|
65
65
|
<th class="w-1"></th>
|
|
66
|
-
{% for name,
|
|
66
|
+
{% for name, prop in model_view._list_props %}
|
|
67
67
|
<th>
|
|
68
|
-
{% if
|
|
69
|
-
{% if request.query_params.get("sortBy") ==
|
|
68
|
+
{% if prop.key in model_view._sort_fields %}
|
|
69
|
+
{% if request.query_params.get("sortBy") == prop.key and request.query_params.get("sort") == "asc" %}
|
|
70
70
|
<a href="{{ request.url.include_query_params(sort='desc') }}"><i class="fa-solid fa-arrow-down"></i> {{ name }}</a>
|
|
71
|
-
{% elif request.query_params.get("sortBy") ==
|
|
71
|
+
{% elif request.query_params.get("sortBy") == prop.key and request.query_params.get("sort") == "desc" %}
|
|
72
72
|
<a href="{{ request.url.include_query_params(sort='asc') }}"><i class="fa-solid fa-arrow-up"></i> {{ name }}</a>
|
|
73
73
|
{% else %}
|
|
74
|
-
<a href="{{ request.url.include_query_params(sortBy=
|
|
74
|
+
<a href="{{ request.url.include_query_params(sortBy=prop.key, sort='asc') }}">{{ name }}</a>
|
|
75
75
|
{% endif %}
|
|
76
76
|
{% else %}
|
|
77
77
|
{{ name }}
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
{% for row in pagination.rows %}
|
|
85
85
|
<tr>
|
|
86
86
|
<td>
|
|
87
|
-
<input type="hidden" value="{{ model_view.
|
|
87
|
+
<input type="hidden" value="{{ model_view.get_prop_value(row, model_view.pk_column) }}">
|
|
88
88
|
<input class="form-check-input m-0 align-middle select-box" type="checkbox" aria-label="Select item">
|
|
89
89
|
</td>
|
|
90
90
|
<td class="text-end">
|
|
@@ -99,14 +99,14 @@
|
|
|
99
99
|
</a>
|
|
100
100
|
{% endif %}
|
|
101
101
|
{% if model_view.can_delete %}
|
|
102
|
-
<a href="#" data-name="{{ model_view.name }}" data-pk="{{ model_view.
|
|
102
|
+
<a href="#" data-name="{{ model_view.name }}" data-pk="{{ model_view.get_prop_value(row, model_view.pk_column) }}" data-url="{{ model_view._url_for_delete(request, row) }}" data-bs-toggle="modal" data-bs-target="#modal-delete" title="Delete">
|
|
103
103
|
<span class="me-1"><i class="fa-solid fa-trash"></i></span>
|
|
104
104
|
</a>
|
|
105
105
|
{% endif %}
|
|
106
106
|
</td>
|
|
107
|
-
{% for name, column in model_view.
|
|
107
|
+
{% for name, column in model_view._list_props %}
|
|
108
108
|
{% set value, formatted_value = model_view.get_list_value(row, column) %}
|
|
109
|
-
{% if column in model_view.
|
|
109
|
+
{% if column in model_view._relation_props %}
|
|
110
110
|
{% if is_list( value ) %}
|
|
111
111
|
<td>
|
|
112
112
|
{% for elem, formatted_elem in zip(value, formatted_value) %}
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
{% endfor %}
|
|
115
115
|
</td>
|
|
116
116
|
{% else %}
|
|
117
|
-
<td><a href="{{ model_view.
|
|
117
|
+
<td><a href="{{ model_view._url_for_details_with_prop(request, row, column) }}">{{ formatted_value }}</a></td>
|
|
118
118
|
{% endif %}
|
|
119
119
|
{% else %}
|
|
120
120
|
<td>{{ formatted_value }}</td>
|
sqladmin/widgets.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import Any
|
|
2
|
+
from typing import Any
|
|
3
3
|
|
|
4
4
|
from markupsafe import Markup
|
|
5
5
|
from wtforms import Field, widgets
|
|
6
6
|
from wtforms.widgets import html_params
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
|
+
"AjaxSelect2Widget",
|
|
9
10
|
"DatePickerWidget",
|
|
10
11
|
"DateTimePickerWidget",
|
|
12
|
+
"Select2TagsWidget",
|
|
11
13
|
"TimePickerWidget",
|
|
12
14
|
]
|
|
13
15
|
|
|
@@ -68,3 +70,30 @@ class AjaxSelect2Widget(widgets.Select):
|
|
|
68
70
|
kwargs["data-json"] = json.dumps([data])
|
|
69
71
|
|
|
70
72
|
return Markup(f"<select {html_params(name=field.name, **kwargs)}></select>")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Select2TagsWidget(widgets.Select):
|
|
76
|
+
def __call__(self, field: Field, **kwargs: Any) -> str:
|
|
77
|
+
kwargs.setdefault("data-role", "select2-tags")
|
|
78
|
+
kwargs.setdefault("data-json", json.dumps(field.data))
|
|
79
|
+
return super().__call__(field, **kwargs)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class FileInputWidget(widgets.FileInput):
|
|
83
|
+
"""
|
|
84
|
+
File input widget with clear checkbox.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
def __call__(self, field: Field, **kwargs: Any) -> str:
|
|
88
|
+
file_input = super().__call__(field, **kwargs)
|
|
89
|
+
checkbox_id = f"{field.id}_checkbox"
|
|
90
|
+
checkbox_label = Markup(
|
|
91
|
+
f'<label class="form-check-label" for="{checkbox_id}">Clear</label>'
|
|
92
|
+
)
|
|
93
|
+
checkbox_input = Markup(
|
|
94
|
+
f'<input class="form-check-input" type="checkbox" id="{checkbox_id}" name="{checkbox_id}">' # noqa: E501
|
|
95
|
+
)
|
|
96
|
+
checkbox = Markup(
|
|
97
|
+
f'<div class="form-check">{checkbox_input}{checkbox_label}</div>'
|
|
98
|
+
)
|
|
99
|
+
return file_input + checkbox
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sqladmin
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: SQLAlchemy admin for FastAPI and Starlette
|
|
5
5
|
Project-URL: Documentation, https://aminalaee.dev/sqladmin
|
|
6
6
|
Project-URL: Issues, https://github.com/aminalaee/sqladmin/issues
|
|
7
7
|
Project-URL: Source, https://github.com/aminalaee/sqladmin
|
|
8
8
|
Author-email: Amin Alaee <mohammadamin.alaee@gmail.com>
|
|
9
|
+
License-Expression: BSD-3-Clause
|
|
9
10
|
License-File: LICENSE.md
|
|
10
11
|
Keywords: admin,fastapi,sqlalchemy,starlette
|
|
11
|
-
Classifier: Development Status ::
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
13
|
Classifier: Environment :: Web Environment
|
|
13
14
|
Classifier: Intended Audience :: Developers
|
|
14
15
|
Classifier: License :: OSI Approved :: BSD License
|
|
@@ -21,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
21
22
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
23
|
Classifier: Topic :: Internet :: WWW/HTTP
|
|
23
24
|
Requires-Python: >=3.7
|
|
24
|
-
Requires-Dist: sqlalchemy
|
|
25
|
+
Requires-Dist: sqlalchemy>=1.4
|
|
25
26
|
Requires-Dist: starlette[full]
|
|
26
27
|
Requires-Dist: typing-extensions>=4.0; python_version < '3.8'
|
|
27
28
|
Requires-Dist: wtforms<4,>=3
|
|
@@ -83,6 +84,11 @@ $ pip install sqladmin
|
|
|
83
84
|
|
|
84
85
|
---
|
|
85
86
|
|
|
87
|
+
## Screenshots
|
|
88
|
+
|
|
89
|
+
<img width="1492" alt="sqladmin-1" src="https://user-images.githubusercontent.com/19784933/208232730-0114a155-2740-4e89-9d73-64a4e51a5cf5.png">
|
|
90
|
+
<img width="1492" alt="sqladmin-2" src="https://user-images.githubusercontent.com/19784933/208232731-6d783dde-b93e-41c0-911b-3d1c3c73f1d5.png">
|
|
91
|
+
|
|
86
92
|
## Quickstart
|
|
87
93
|
|
|
88
94
|
Let's define an example SQLAlchemy model:
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
sqladmin/__init__.py,sha256=
|
|
2
|
-
sqladmin/_queries.py,sha256=
|
|
3
|
-
sqladmin/_types.py,sha256=
|
|
4
|
-
sqladmin/_validators.py,sha256=
|
|
5
|
-
sqladmin/ajax.py,sha256=
|
|
6
|
-
sqladmin/application.py,sha256=
|
|
7
|
-
sqladmin/authentication.py,sha256=
|
|
1
|
+
sqladmin/__init__.py,sha256=BcFoQ3KjLGs4Sh3evnyrQABVOiysdvUnIfc_4Xo5Dbg,224
|
|
2
|
+
sqladmin/_queries.py,sha256=maNxo8ZWHJys3XvqB5QLLQfMibUvmFEZ4Ufjd_rsN4I,8227
|
|
3
|
+
sqladmin/_types.py,sha256=REixpHnnD4Qytug58b5hbY9B8MsNbZqWI2bJ8jUhCeI,277
|
|
4
|
+
sqladmin/_validators.py,sha256=w0siGhZQq4MD__lu9Edua9DgMOoKET_kk-alpARFHIM,1604
|
|
5
|
+
sqladmin/ajax.py,sha256=WcukKZXTwGM8TUSyQbYYMiHiMeBlwpVA6Cp862rs4ic,2473
|
|
6
|
+
sqladmin/application.py,sha256=xdDsT2pcRAPIKC11d9JncSSOhp1W1kQXa84O2kooS_w,21094
|
|
7
|
+
sqladmin/authentication.py,sha256=p6xqVhYlCd0jM6kHdCFGHnOfdIBwcpXqYqpeoj5STIg,2202
|
|
8
8
|
sqladmin/exceptions.py,sha256=804ZRBRXh05zobafOHIdwmOeEK-cXZ3sQBu0OHSjtxI,210
|
|
9
|
-
sqladmin/fields.py,sha256=
|
|
9
|
+
sqladmin/fields.py,sha256=rWqrXW722gOYlTFSG9y_Kjs3HlfOUWHynDJBd-lB0i8,11864
|
|
10
10
|
sqladmin/formatters.py,sha256=K06la0mm9-Bs5UA9L6KGJC_X_lV3UHdJ3ENI6j9j2Zg,480
|
|
11
|
-
sqladmin/forms.py,sha256=
|
|
12
|
-
sqladmin/helpers.py,sha256=
|
|
13
|
-
sqladmin/models.py,sha256=
|
|
11
|
+
sqladmin/forms.py,sha256=kPHx-_VSxENicKM1_Pdmyg02frwOI17ixbytyA6mNlQ,19603
|
|
12
|
+
sqladmin/helpers.py,sha256=GRSxbi_anqZOyjQaJomYJi96dODPAF_D1FnTHufPX-c,6193
|
|
13
|
+
sqladmin/models.py,sha256=OjrNzMvxNnbsE2yI8hWzrLuJx8vfWg4IuI6UJRBeb6s,35169
|
|
14
14
|
sqladmin/pagination.py,sha256=AmaZ5xNgPdBqTURYdOltz5IcSz8pY4qGQsr8evpUtHk,2256
|
|
15
15
|
sqladmin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
sqladmin/widgets.py,sha256=
|
|
16
|
+
sqladmin/widgets.py,sha256=NQZH7byJbUaY8O_U-1iv0W0Btiu3LuUuBRmhe58Ur2M,3019
|
|
17
17
|
sqladmin/statics/css/flatpickr.min.css,sha256=GzSkJVLJbxDk36qko2cnawOGiqz_Y8GsQv_jMTUrx1Q,16166
|
|
18
18
|
sqladmin/statics/css/fontawesome.min.css,sha256=z9NKRrVjN9Zj8OCp7yFV4PlxGOqT4AaJCOy-rnQ7Rig,68945
|
|
19
19
|
sqladmin/statics/css/main.css,sha256=G1fZ4-mnRIXSXEXNHIAMGyegV-46bSYxjxwmwud30IE,46
|
|
@@ -23,23 +23,23 @@ sqladmin/statics/css/tabler.min.css,sha256=dHSje6bwxNEXwFv0QkwGUwjjrJb5pIgiltBrU
|
|
|
23
23
|
sqladmin/statics/js/bootstrap.min.js,sha256=5dHuQEbO64HT5DMJ0FO0I7hwGOYMTPDdjufF0-npBGU,62399
|
|
24
24
|
sqladmin/statics/js/flatpickr.min.js,sha256=P3cmJKYotkCthfbkx0ci27L0y3mp2ZlCJ-RrV3oOsDE,58060
|
|
25
25
|
sqladmin/statics/js/jquery.min.js,sha256=_xUj-3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej_m4,89501
|
|
26
|
-
sqladmin/statics/js/main.js,sha256=
|
|
26
|
+
sqladmin/statics/js/main.js,sha256=2lRY5ws_9urCFsOU5ryp7ZkyM-w-flXBSEAxUsxXxBM,3831
|
|
27
27
|
sqladmin/statics/js/popper.min.js,sha256=wZjZsjDhPsJ8oPi__hLJzWmP9Fj30Vm0c_9jALIiyjE,19167
|
|
28
28
|
sqladmin/statics/js/select2.full.min.js,sha256=XG_auAy4aieWldzMImofrFDiySK-pwJC7aoo9St7rS0,79212
|
|
29
29
|
sqladmin/statics/js/tabler.min.js,sha256=l-Tz5LXKidfgYBYmcKJIjSYCoa0iVcSW03rLL2oXJcU,137925
|
|
30
30
|
sqladmin/statics/webfonts/fa-solid-900.ttf,sha256=F4IVa_ogVNtCkne0LxQymKHOA0N8BeJ3nKeHURKxnTw,303480
|
|
31
31
|
sqladmin/statics/webfonts/fa-solid-900.woff2,sha256=GwmfiMBu0IaYclYcFX8OycvhM6CTnZ7OTuHh9UvUaD0,126828
|
|
32
32
|
sqladmin/templates/base.html,sha256=mY3cL4oxSUpp4map0KqfcSiXFpYfiUY8dCMys_sASCo,1739
|
|
33
|
-
sqladmin/templates/create.html,sha256=
|
|
34
|
-
sqladmin/templates/details.html,sha256
|
|
35
|
-
sqladmin/templates/edit.html,sha256=
|
|
33
|
+
sqladmin/templates/create.html,sha256=gcnlfR6zuZpO2WuvOuHrLwyYniLSexA7An6egviTu34,1732
|
|
34
|
+
sqladmin/templates/details.html,sha256=7MIUvbVtB51BIwAqg08jSItNTIfXSlcbkID5Tai_SM4,2574
|
|
35
|
+
sqladmin/templates/edit.html,sha256=BZ365fBBo62qkR_aGotDFx5yrdoCOTdkQagD4oL87MA,1906
|
|
36
36
|
sqladmin/templates/error.html,sha256=DGmfAYQB5eYpo1nfK_rDa1-YQ93OR5CKRkWl7x--ajE,282
|
|
37
37
|
sqladmin/templates/index.html,sha256=4JMiiNqyHkriMjaXFgaJ1OGqPMEQKFZVr3bzZUzU_zU,63
|
|
38
38
|
sqladmin/templates/layout.html,sha256=rFMc-m77oVjL9anf6i8PmZlzUHmU_E6Dphu-WP0Tawo,2821
|
|
39
|
-
sqladmin/templates/list.html,sha256=
|
|
39
|
+
sqladmin/templates/list.html,sha256=QlnpuvnY4BbTbLPt0PymrDG0bcAo4-8RIYaaX3X0sNY,8467
|
|
40
40
|
sqladmin/templates/login.html,sha256=owaAUlVpHS1bmPXDVPRvKvGWMbWW8K8xsIaagLYp3wQ,1475
|
|
41
41
|
sqladmin/templates/modals/delete.html,sha256=8K4iNkszaG3Qopt22OLTXxsLCsDidzjhtPQchyBwVLI,1093
|
|
42
|
-
sqladmin-0.
|
|
43
|
-
sqladmin-0.
|
|
44
|
-
sqladmin-0.
|
|
45
|
-
sqladmin-0.
|
|
42
|
+
sqladmin-0.10.0.dist-info/METADATA,sha256=48ehxl49nFEuOn8YJi8qyb1iMPfcequilFDwSbrMy5o,5039
|
|
43
|
+
sqladmin-0.10.0.dist-info/WHEEL,sha256=Fd6mP6ydyRguakwUJ05oBE7fh2IPxgtDN9IwHJ9OqJQ,87
|
|
44
|
+
sqladmin-0.10.0.dist-info/licenses/LICENSE.md,sha256=4zzpHQMPtND4hzIgJA5qnb4R_wRBWJlYGqNrZolBeP8,1488
|
|
45
|
+
sqladmin-0.10.0.dist-info/RECORD,,
|
|
File without changes
|