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.
@@ -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.get_attr_value(model, model_view.pk_column) }}</h3>
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, attr in model_view._details_attrs %}
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, attr) %}
22
- {% if attr in model_view._relations %}
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._url_for_details_with_attr(request, model, attr) }}">{{ formatted_value }}</a></td>
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.get_attr_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">
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>
@@ -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">
@@ -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, attr in model_view._list_attrs %}
66
+ {% for name, prop in model_view._list_props %}
67
67
  <th>
68
- {% if attr in model_view._sort_fields %}
69
- {% if request.query_params.get("sortBy") == attr.key and request.query_params.get("sort") == "asc" %}
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") == attr.key and request.query_params.get("sort") == "desc" %}
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=attr.key, sort='asc') }}">{{ name }}</a>
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.get_attr_value(row, model_view.pk_column) }}">
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.get_attr_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">
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._list_attrs %}
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._relations %}
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._url_for_details_with_attr(request, row, column) }}">{{ formatted_value }}</a></td>
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, Dict
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.8.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 :: 3 - Alpha
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<1.5,>=1.4
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=1imqHe-i74s92Gj3N5aA1YHAGbSrsFMgsXMu4ZSGkwM,223
2
- sqladmin/_queries.py,sha256=kXkFXYTcUCoivAgVOC9jaaFHKeB_FngJOho0L0RZo1Y,7991
3
- sqladmin/_types.py,sha256=sCIKqC3jbW2OBoLAcSi8kXBwKpd78kG4kWD-cSVH9S0,278
4
- sqladmin/_validators.py,sha256=W5PUaWCrK0d5Wi1MUxf8RNe7HOuJPjf1Uq12lBtTYIg,888
5
- sqladmin/ajax.py,sha256=n3zPHAWC2m3v34QUV2XV8HhG4zZHW6vwkXcKvIgTZDA,2479
6
- sqladmin/application.py,sha256=S_x5xlXmxGtMJt9_cVHDLMh66pUo06VOofVOPJpfaFI,19962
7
- sqladmin/authentication.py,sha256=bPUxMgJJUglNAM7s_PZkKNmWVp0J3Vf12TfwwRQd6vs,2027
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=PxN6F5u-POrggML1DBd5nU4YLMZavRh4Gk4MfGKsy-4,10703
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=nFl4ubCHGCp6LmZeBugLgpCFhkKoL3FSfFy6HUumAd8,18264
12
- sqladmin/helpers.py,sha256=C1XJ5IgQGxLU4owMc8YDaJFCp1o6WzDzGhhM6n0ppNA,3969
13
- sqladmin/models.py,sha256=MYK9XUNbjeZIuSXHhatyf_77YjSjcGQSeXnhEEUQHbk,35151
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=0GHzrtX6zmkeFjs-AdOa69cDC4mpm-_-a2RMuNM-f0w,2004
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=hHOHsHkWNahjtc9-Ua0Av1RGQAy4jfFFuVBwq6EA3Ds,3466
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=tLHupg0Wycvo6ahMCH0TvQ-B-wZHTE-KWdWaeSWjD5Q,1702
34
- sqladmin/templates/details.html,sha256=-DhCynXIoH1K--blS6-7tLyQuxCm1P4M_6E5_0e02gI,2569
35
- sqladmin/templates/edit.html,sha256=7O-EHP_Na7jpgmf-NffRqK4cYs9AiaSsZ7i8F6jrpuQ,1876
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=bMMxcwRs1QirxB8LE86a_IfVAw64obPoPGfKk2e-Eww,8458
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.8.0.dist-info/METADATA,sha256=TR6rcJ9p0MWeDUx2pBDk621Nb6-u-fnn85vkaEf2qDM,4706
43
- sqladmin-0.8.0.dist-info/WHEEL,sha256=NaLmgHHW_f9jTvv_wRh9vcK7c7EK9o5fwsIXMOzoGgM,87
44
- sqladmin-0.8.0.dist-info/licenses/LICENSE.md,sha256=4zzpHQMPtND4hzIgJA5qnb4R_wRBWJlYGqNrZolBeP8,1488
45
- sqladmin-0.8.0.dist-info/RECORD,,
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.11.1
2
+ Generator: hatchling 1.13.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any