sqladmin 0.20.1__py3-none-any.whl → 0.22.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.
@@ -1,208 +1,285 @@
1
1
  {% extends "sqladmin/layout.html" %}
2
2
  {% block content %}
3
- <div class="col-12">
4
- <div class="card">
5
- <div class="card-header">
6
- <h3 class="card-title">{{ model_view.name_plural }}</h3>
7
- <div class="ms-auto">
8
- {% if model_view.can_export %}
9
- {% if model_view.export_types | length > 1 %}
10
- <div class="ms-3 d-inline-block dropdown">
11
- <a href="#" class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton1" data-bs-toggle="dropdown"
12
- aria-expanded="false">
13
- Export
14
- </a>
15
- <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
16
- {% for export_type in model_view.export_types %}
17
- <li><a class="dropdown-item"
18
- href="{{ url_for('admin:export', identity=model_view.identity, export_type=export_type) }}">{{
19
- export_type | upper }}</a></li>
20
- {% endfor %}
21
- </ul>
22
- </div>
23
- {% elif model_view.export_types | length == 1 %}
24
- <div class="ms-3 d-inline-block">
25
- <a href="{{ url_for('admin:export', identity=model_view.identity, export_type=model_view.export_types[0]) }}"
26
- class="btn btn-secondary">
27
- Export
28
- </a>
29
- </div>
30
- {% endif %}
31
- {% endif %}
32
- {% if model_view.can_create %}
33
- <div class="ms-3 d-inline-block">
34
- <a href="{{ url_for('admin:create', identity=model_view.identity) }}" class="btn btn-primary">
35
- + New {{ model_view.name }}
36
- </a>
37
- </div>
38
- {% endif %}
39
- </div>
40
- </div>
41
- <div class="card-body border-bottom py-3">
42
- <div class="d-flex justify-content-between">
43
- <div class="dropdown col-4">
44
- <button {% if not model_view.can_delete and not model_view._custom_actions_in_list %} disabled {% endif %}
45
- class="btn btn-light dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown"
46
- aria-haspopup="true" aria-expanded="false">
47
- Actions
48
- </button>
49
- {% if model_view.can_delete or model_view._custom_actions_in_list %}
50
- <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
51
- {% if model_view.can_delete %}
52
- <a class="dropdown-item" id="action-delete" href="#" data-name="{{ model_view.name }}"
53
- data-url="{{ url_for('admin:delete', identity=model_view.identity) }}" data-bs-toggle="modal"
54
- data-bs-target="#modal-delete">Delete selected items</a>
55
- {% endif %}
56
- {% for custom_action, label in model_view._custom_actions_in_list.items() %}
57
- {% if custom_action in model_view._custom_actions_confirmation %}
58
- <a class="dropdown-item" id="action-customconfirm-{{ custom_action }}" href="#" data-bs-toggle="modal"
59
- data-bs-target="#modal-confirmation-{{ custom_action }}">
60
- {{ label }}
61
- </a>
62
- {% else %}
63
- <a class="dropdown-item" id="action-custom-{{ custom_action }}" href="#"
64
- data-url="{{ model_view._url_for_action(request, custom_action) }}">
65
- {{ label }}
66
- </a>
67
- {% endif %}
68
- {% endfor %}
69
- </div>
70
- {% endif %}
71
- </div>
72
- {% if model_view.column_searchable_list %}
73
- <div class="col-md-4 text-muted">
74
- <div class="input-group">
75
- <input id="search-input" type="text" class="form-control"
76
- placeholder="Search: {{ model_view.search_placeholder() }}"
77
- value="{{ request.query_params.get('search', '') }}">
78
- <button id="search-button" class="btn" type="button">Search</button>
79
- <button id="search-reset" class="btn" type="button" {% if not request.query_params.get('search')
80
- %}disabled{% endif %}><i class="fa-solid fa-times"></i></button>
3
+ <div class="container-fluid">
4
+ <div class="row">
5
+ <div class="col-12">
6
+ <div class="d-flex">
7
+ <div class="flex-grow-1 me-2">
8
+ <div class="card">
9
+ <div class="card-header">
10
+ <h3 class="card-title">{{ model_view.name_plural }}</h3>
11
+ <div class="ms-auto">
12
+ {% if model_view.can_export %}
13
+ {% if model_view.export_types | length > 1 %}
14
+ <div class="ms-3 d-inline-block dropdown">
15
+ <a href="#" class="btn btn-secondary dropdown-toggle" id="dropdownMenuButton1" data-bs-toggle="dropdown"
16
+ aria-expanded="false">
17
+ Export
18
+ </a>
19
+ <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
20
+ {% for export_type in model_view.export_types %}
21
+ <li><a class="dropdown-item"
22
+ href="{{ url_for('admin:export', identity=model_view.identity, export_type=export_type) }}">{{
23
+ export_type | upper }}</a></li>
24
+ {% endfor %}
25
+ </ul>
26
+ </div>
27
+ {% elif model_view.export_types | length == 1 %}
28
+ <div class="ms-3 d-inline-block">
29
+ <a href="{{ url_for('admin:export', identity=model_view.identity, export_type=model_view.export_types[0]) }}"
30
+ class="btn btn-secondary">
31
+ Export
32
+ </a>
33
+ </div>
34
+ {% endif %}
35
+ {% endif %}
36
+ {% if model_view.can_create %}
37
+ <div class="ms-3 d-inline-block">
38
+ <a href="{{ url_for('admin:create', identity=model_view.identity) }}" class="btn btn-primary">
39
+ + New {{ model_view.name }}
40
+ </a>
41
+ </div>
42
+ {% endif %}
43
+ </div>
44
+ </div>
45
+ <div class="card-body border-bottom py-3">
46
+ <div class="d-flex justify-content-between">
47
+ <div class="dropdown col-4">
48
+ <button {% if not model_view.can_delete and not model_view._custom_actions_in_list %} disabled {% endif %}
49
+ class="btn btn-light dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown"
50
+ aria-haspopup="true" aria-expanded="false">
51
+ Actions
52
+ </button>
53
+ {% if model_view.can_delete or model_view._custom_actions_in_list %}
54
+ <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
55
+ {% if model_view.can_delete %}
56
+ <a class="dropdown-item" id="action-delete" href="#" data-name="{{ model_view.name }}"
57
+ data-url="{{ url_for('admin:delete', identity=model_view.identity) }}" data-bs-toggle="modal"
58
+ data-bs-target="#modal-delete">Delete selected items</a>
59
+ {% endif %}
60
+ {% for custom_action, label in model_view._custom_actions_in_list.items() %}
61
+ {% if custom_action in model_view._custom_actions_confirmation %}
62
+ <a class="dropdown-item" id="action-customconfirm-{{ custom_action }}" href="#" data-bs-toggle="modal"
63
+ data-bs-target="#modal-confirmation-{{ custom_action }}">
64
+ {{ label }}
65
+ </a>
66
+ {% else %}
67
+ <a class="dropdown-item" id="action-custom-{{ custom_action }}" href="#"
68
+ data-url="{{ model_view._url_for_action(request, custom_action) }}">
69
+ {{ label }}
70
+ </a>
71
+ {% endif %}
72
+ {% endfor %}
73
+ </div>
74
+ {% endif %}
75
+ </div>
76
+ {% if model_view.column_searchable_list %}
77
+ <div class="col-md-4 text-muted">
78
+ <div class="input-group">
79
+ <input id="search-input" type="text" class="form-control"
80
+ placeholder="Search: {{ model_view.search_placeholder() }}"
81
+ value="{{ request.query_params.get('search', '') }}">
82
+ <button id="search-button" class="btn" type="button">Search</button>
83
+ <button id="search-reset" class="btn" type="button" {% if not request.query_params.get('search')
84
+ %}disabled{% endif %}><i class="fa-solid fa-times"></i></button>
85
+ </div>
86
+ </div>
87
+ {% endif %}
88
+ </div>
89
+ </div>
90
+ <div class="table-responsive">
91
+ <table class="table card-table table-vcenter text-nowrap">
92
+ <thead>
93
+ <tr>
94
+ <th class="w-1"><input class="form-check-input m-0 align-middle" type="checkbox" aria-label="Select all"
95
+ id="select-all"></th>
96
+ <th class="w-1"></th>
97
+ {% for name in model_view._list_prop_names %}
98
+ {% set label = model_view._column_labels.get(name, name) %}
99
+ <th>
100
+ {% if name in model_view._sort_fields %}
101
+ {% if request.query_params.get("sortBy") == name and request.query_params.get("sort") == "asc" %}
102
+ <a href="{{ request.url.include_query_params(sort='desc') }}"><i class="fa-solid fa-arrow-up"></i> {{
103
+ label }}</a>
104
+ {% elif request.query_params.get("sortBy") == name and request.query_params.get("sort") == "desc" %}
105
+ <a href="{{ request.url.include_query_params(sort='asc') }}"><i class="fa-solid fa-arrow-down"></i> {{ label
106
+ }}</a>
107
+ {% else %}
108
+ <a href="{{ request.url.include_query_params(sortBy=name, sort='asc') }}">{{ label }}</a>
109
+ {% endif %}
110
+ {% else %}
111
+ {{ label }}
112
+ {% endif %}
113
+ </th>
114
+ {% endfor %}
115
+ </tr>
116
+ </thead>
117
+ <tbody>
118
+ {% for row in pagination.rows %}
119
+ <tr>
120
+ <td>
121
+ <input type="hidden" value="{{ get_object_identifier(row) }}">
122
+ <input class="form-check-input m-0 align-middle select-box" type="checkbox" aria-label="Select item">
123
+ </td>
124
+ <td class="text-end">
125
+ {% if model_view.can_view_details %}
126
+ <a href="{{ model_view._build_url_for('admin:details', request, row) }}" data-bs-toggle="tooltip"
127
+ data-bs-placement="top" title="View">
128
+ <span class="me-1"><i class="fa-solid fa-eye"></i></span>
129
+ </a>
130
+ {% endif %}
131
+ {% if model_view.can_edit %}
132
+ <a href="{{ model_view._build_url_for('admin:edit', request, row) }}" data-bs-toggle="tooltip"
133
+ data-bs-placement="top" title="Edit">
134
+ <span class="me-1"><i class="fa-solid fa-pen-to-square"></i></span>
135
+ </a>
136
+ {% endif %}
137
+ {% if model_view.can_delete %}
138
+ <a href="#" data-name="{{ model_view.name }}" data-pk="{{ get_object_identifier(row) }}"
139
+ data-url="{{ model_view._url_for_delete(request, row) }}" data-bs-toggle="modal"
140
+ data-bs-target="#modal-delete" title="Delete">
141
+ <span class="me-1"><i class="fa-solid fa-trash"></i></span>
142
+ </a>
143
+ {% endif %}
144
+ </td>
145
+ {% for name in model_view._list_prop_names %}
146
+ {% set value, formatted_value = model_view.get_list_value(row, name) %}
147
+ {% if name in model_view._relation_names %}
148
+ {% if is_list( value ) %}
149
+ <td>
150
+ {% for elem, formatted_elem in zip(value, formatted_value) %}
151
+ {% if model_view.show_compact_lists %}
152
+ <a href="{{ model_view._build_url_for('admin:details', request, elem) }}">({{ formatted_elem }})</a>
153
+ {% else %}
154
+ <a href="{{ model_view._build_url_for('admin:details', request, elem) }}">{{ formatted_elem }}</a><br/>
155
+ {% endif %}
156
+ {% endfor %}
157
+ </td>
158
+ {% else %}
159
+ <td><a href="{{ model_view._url_for_details_with_prop(request, row, name) }}">{{ formatted_value }}</a></td>
160
+ {% endif %}
161
+ {% else %}
162
+ <td>{{ formatted_value }}</td>
163
+ {% endif %}
164
+ {% endfor %}
165
+ </tr>
166
+ {% endfor %}
167
+ </tbody>
168
+ </table>
169
+ </div>
170
+ <div class="card-footer d-flex justify-content-between align-items-center gap-2">
171
+ <p class="m-0 text-muted">Showing <span>{{ ((pagination.page - 1) * pagination.page_size) + 1 }}</span> to
172
+ <span>{{ min(pagination.page * pagination.page_size, pagination.count) }}</span> of <span>{{ pagination.count
173
+ }}</span> items
174
+ </p>
175
+ <ul class="pagination m-0 ms-auto">
176
+ <li class="page-item {% if not pagination.has_previous %}disabled{% endif %}">
177
+ {% if pagination.has_previous %}
178
+ <a class="page-link" href="{{ pagination.previous_page.url }}">
179
+ {% else %}
180
+ <a class="page-link" href="#">
181
+ {% endif %}
182
+ <i class="fa-solid fa-chevron-left"></i>
183
+ prev
184
+ </a>
185
+ </li>
186
+ {% for page_control in pagination.page_controls %}
187
+ <li class="page-item {% if page_control.number == pagination.page %}active{% endif %}"><a class="page-link"
188
+ href="{{ page_control.url }}">{{ page_control.number }}</a></li>
189
+ {% endfor %}
190
+ <li class="page-item {% if not pagination.has_next %}disabled{% endif %}">
191
+ {% if pagination.has_next %}
192
+ <a class="page-link" href="{{ pagination.next_page.url }}">
193
+ {% else %}
194
+ <a class="page-link" href="#">
195
+ {% endif %}
196
+ next
197
+ <i class="fa-solid fa-chevron-right"></i>
198
+ </a>
199
+ </li>
200
+ </ul>
201
+ <div class="dropdown text-muted">
202
+ Show
203
+ <a href="#" class="btn btn-sm btn-light dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
204
+ aria-expanded="false">
205
+ {{ request.query_params.get("pageSize") or model_view.page_size }} / Page
206
+ </a>
207
+ <div class="dropdown-menu">
208
+ {% for page_size_option in model_view.page_size_options %}
209
+ <a class="dropdown-item" href="{{ request.url.include_query_params(pageSize=page_size_option, page=pagination.resize(page_size_option).page) }}">
210
+ {{ page_size_option }} / Page
211
+ </a>
212
+ {% endfor %}
213
+ </div>
214
+ </div>
215
+ </div>
81
216
  </div>
82
217
  </div>
83
- {% endif %}
84
- </div>
85
- </div>
86
- <div class="table-responsive">
87
- <table class="table card-table table-vcenter text-nowrap">
88
- <thead>
89
- <tr>
90
- <th class="w-1"><input class="form-check-input m-0 align-middle" type="checkbox" aria-label="Select all"
91
- id="select-all"></th>
92
- <th class="w-1"></th>
93
- {% for name in model_view._list_prop_names %}
94
- {% set label = model_view._column_labels.get(name, name) %}
95
- <th>
96
- {% if name in model_view._sort_fields %}
97
- {% if request.query_params.get("sortBy") == name and request.query_params.get("sort") == "asc" %}
98
- <a href="{{ request.url.include_query_params(sort='desc') }}"><i class="fa-solid fa-arrow-up"></i> {{
99
- label }}</a>
100
- {% elif request.query_params.get("sortBy") == name and request.query_params.get("sort") == "desc" %}
101
- <a href="{{ request.url.include_query_params(sort='asc') }}"><i class="fa-solid fa-arrow-down"></i> {{ label
102
- }}</a>
103
- {% else %}
104
- <a href="{{ request.url.include_query_params(sortBy=name, sort='asc') }}">{{ label }}</a>
105
- {% endif %}
218
+ {% if model_view.get_filters() %}
219
+ <div class="col-md-3" style="width: 300px; flex-shrink: 0;">
220
+ <div id="filter-sidebar" class="card">
221
+ <div class="card-header">
222
+ <h3 class="card-title">Filters</h3>
223
+ </div>
224
+ <div class="card-body">
225
+ {% for filter in model_view.get_filters() %}
226
+ {% if filter.has_operator %}
227
+ <div class="mb-3">
228
+ <div class="fw-bold text-truncate">{{ filter.title }}</div>
229
+ <div>
230
+ <!-- Show current filter if active -->
231
+ {% set current_filter = request.query_params.get(filter.parameter_name, '') %}
232
+ {% set current_op = request.query_params.get(filter.parameter_name + '_op', '') %}
233
+ {% if current_filter %}
234
+ <div class="mb-2 text-muted small">
235
+ Current: {{ current_op }} {{ current_filter }}
236
+ <a href="{{ request.url.remove_query_params(filter.parameter_name).remove_query_params(filter.parameter_name + '_op') }}" class="text-decoration-none">[Clear]</a>
237
+ </div>
238
+ {% endif %}
239
+ <!-- Single form with dropdown for operations -->
240
+ <form method="get" class="d-flex flex-column" style="gap: 8px;">
241
+ <!-- Preserve existing query parameters -->
242
+ {% for key, value in request.query_params.items() %}
243
+ {% if key != filter.parameter_name and key != filter.parameter_name + '_op' %}
244
+ <input type="hidden" name="{{ key }}" value="{{ value }}">
245
+ {% endif %}
246
+ {% endfor %}
247
+ <!-- Operation dropdown -->
248
+ <select name="{{ filter.parameter_name }}_op" class="form-select form-select-sm" required>
249
+ <option value="">Select operation...</option>
250
+ {% for op_value, op_label in filter.get_operation_options_for_model(model_view.model) %}
251
+ <option value="{{ op_value }}" {% if current_op == op_value %}selected{% endif %}>{{ op_label }}</option>
252
+ {% endfor %}
253
+ </select>
254
+ <!-- Value input -->
255
+ <input type="text"
256
+ name="{{ filter.parameter_name }}"
257
+ placeholder="Enter value"
258
+ class="form-control form-control-sm"
259
+ value="{{ current_filter }}"
260
+ required>
261
+ <button type="submit" class="btn btn-sm btn-outline-primary">Apply Filter</button>
262
+ </form>
263
+ </div>
264
+ </div>
106
265
  {% else %}
107
- {{ label }}
108
- {% endif %}
109
- </th>
110
- {% endfor %}
111
- </tr>
112
- </thead>
113
- <tbody>
114
- {% for row in pagination.rows %}
115
- <tr>
116
- <td>
117
- <input type="hidden" value="{{ get_object_identifier(row) }}">
118
- <input class="form-check-input m-0 align-middle select-box" type="checkbox" aria-label="Select item">
119
- </td>
120
- <td class="text-end">
121
- {% if model_view.can_view_details %}
122
- <a href="{{ model_view._build_url_for('admin:details', request, row) }}" data-bs-toggle="tooltip"
123
- data-bs-placement="top" title="View">
124
- <span class="me-1"><i class="fa-solid fa-eye"></i></span>
125
- </a>
126
- {% endif %}
127
- {% if model_view.can_edit %}
128
- <a href="{{ model_view._build_url_for('admin:edit', request, row) }}" data-bs-toggle="tooltip"
129
- data-bs-placement="top" title="Edit">
130
- <span class="me-1"><i class="fa-solid fa-pen-to-square"></i></span>
131
- </a>
132
- {% endif %}
133
- {% if model_view.can_delete %}
134
- <a href="#" data-name="{{ model_view.name }}" data-pk="{{ get_object_identifier(row) }}"
135
- data-url="{{ model_view._url_for_delete(request, row) }}" data-bs-toggle="modal"
136
- data-bs-target="#modal-delete" title="Delete">
137
- <span class="me-1"><i class="fa-solid fa-trash"></i></span>
138
- </a>
266
+ <!-- Fallback for other filter types -->
267
+ <div class="mb-3">
268
+ <div class="fw-bold text-truncate">{{ filter.title }}</div>
269
+ <div>
270
+ {% for lookup in filter.lookups(request, model_view.model, model_view._run_arbitrary_query) %}
271
+ <a href="{{ request.url.include_query_params(**{filter.parameter_name: lookup[0]}) }}" class="d-block text-decoration-none text-truncate">
272
+ {{ lookup[1] }}
273
+ </a>
274
+ {% endfor %}
275
+ </div>
276
+ </div>
139
277
  {% endif %}
140
- </td>
141
- {% for name in model_view._list_prop_names %}
142
- {% set value, formatted_value = model_view.get_list_value(row, name) %}
143
- {% if name in model_view._relation_names %}
144
- {% if is_list( value ) %}
145
- <td>
146
- {% for elem, formatted_elem in zip(value, formatted_value) %}
147
- <a href="{{ model_view._build_url_for('admin:details', request, elem) }}">({{ formatted_elem }})</a>
148
278
  {% endfor %}
149
- </td>
150
- {% else %}
151
- <td><a href="{{ model_view._url_for_details_with_prop(request, row, name) }}">{{ formatted_value }}</a></td>
152
- {% endif %}
153
- {% else %}
154
- <td>{{ formatted_value }}</td>
155
- {% endif %}
156
- {% endfor %}
157
- </tr>
158
- {% endfor %}
159
- </tbody>
160
- </table>
161
- </div>
162
- <div class="card-footer d-flex justify-content-between align-items-center gap-2">
163
- <p class="m-0 text-muted">Showing <span>{{ ((pagination.page - 1) * pagination.page_size) + 1 }}</span> to
164
- <span>{{ min(pagination.page * pagination.page_size, pagination.count) }}</span> of <span>{{ pagination.count
165
- }}</span> items
166
- </p>
167
- <ul class="pagination m-0 ms-auto">
168
- <li class="page-item {% if not pagination.has_previous %}disabled{% endif %}">
169
- {% if pagination.has_previous %}
170
- <a class="page-link" href="{{ pagination.previous_page.url }}">
171
- {% else %}
172
- <a class="page-link" href="#">
173
- {% endif %}
174
- <i class="fa-solid fa-chevron-left"></i>
175
- prev
176
- </a>
177
- </li>
178
- {% for page_control in pagination.page_controls %}
179
- <li class="page-item {% if page_control.number == pagination.page %}active{% endif %}"><a class="page-link"
180
- href="{{ page_control.url }}">{{ page_control.number }}</a></li>
181
- {% endfor %}
182
- <li class="page-item {% if not pagination.has_next %}disabled{% endif %}">
183
- {% if pagination.has_next %}
184
- <a class="page-link" href="{{ pagination.next_page.url }}">
185
- {% else %}
186
- <a class="page-link" href="#">
187
- {% endif %}
188
- next
189
- <i class="fa-solid fa-chevron-right"></i>
190
- </a>
191
- </li>
192
- </ul>
193
- <div class="dropdown text-muted">
194
- Show
195
- <a href="#" class="btn btn-sm btn-light dropdown-toggle" data-toggle="dropdown" aria-haspopup="true"
196
- aria-expanded="false">
197
- {{ request.query_params.get("pageSize") or model_view.page_size }} / Page
198
- </a>
199
- <div class="dropdown-menu">
200
- {% for page_size_option in model_view.page_size_options %}
201
- <a class="dropdown-item" href="{{ request.url.include_query_params(pageSize=page_size_option, page=pagination.resize(page_size_option).page) }}">
202
- {{ page_size_option }} / Page
203
- </a>
204
- {% endfor %}
279
+ </div>
280
+ </div>
205
281
  </div>
282
+ {% endif %}
206
283
  </div>
207
284
  </div>
208
285
  </div>
@@ -1,8 +1,8 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: sqladmin
3
- Version: 0.20.1
3
+ Version: 0.22.0
4
4
  Summary: SQLAlchemy admin for FastAPI and Starlette
5
- Project-URL: Documentation, https://aminalaee.dev/sqladmin
5
+ Project-URL: Documentation, https://aminalaee.github.io/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 <me@aminalaee.dev>
@@ -15,13 +15,14 @@ Classifier: Intended Audience :: Developers
15
15
  Classifier: License :: OSI Approved :: BSD License
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python
18
- Classifier: Programming Language :: Python :: 3.8
19
18
  Classifier: Programming Language :: Python :: 3.9
20
19
  Classifier: Programming Language :: Python :: 3.10
21
20
  Classifier: Programming Language :: Python :: 3.11
22
21
  Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
23
24
  Classifier: Topic :: Internet :: WWW/HTTP
24
- Requires-Python: >=3.8
25
+ Requires-Python: >=3.10
25
26
  Requires-Dist: jinja2
26
27
  Requires-Dist: python-multipart
27
28
  Requires-Dist: sqlalchemy>=1.4
@@ -72,7 +73,7 @@ Main features include:
72
73
 
73
74
  ---
74
75
 
75
- **Documentation**: [https://aminalaee.dev/sqladmin](https://aminalaee.dev/sqladmin)
76
+ **Documentation**: [https://aminalaee.github.io/sqladmin](https://aminalaee.github.io/sqladmin)
76
77
 
77
78
  **Source Code**: [https://github.com/aminalaee/sqladmin](https://github.com/aminalaee/sqladmin)
78
79
 
@@ -1,24 +1,25 @@
1
- sqladmin/__init__.py,sha256=3kjWCBseZv6vxNmMtKgrBicZUgE93ZwOF14aquXK_p0,216
2
- sqladmin/_menu.py,sha256=V6uKvIJGKrC0kmXq4M-DAgvPoHvgoGgKAw47OjsswGA,2609
1
+ sqladmin/__init__.py,sha256=HgCrQImuNIFeVjI_W2hpvmsR-I03N5VJjESatR_jeW0,216
2
+ sqladmin/_menu.py,sha256=kjBIk_PIpa__C-gSRPIWv9OEQR1uFB4M_1LOU5MHYu0,2608
3
3
  sqladmin/_queries.py,sha256=KqxMABvepoA0j-8Xizg6ASYS-sZDSdm5iFlU74vilQY,9697
4
- sqladmin/_types.py,sha256=3Zs0aPb14OS-9leahKxxzFopnIOiNftPZwdUmFDBKog,347
4
+ sqladmin/_types.py,sha256=gFZIAM1rBDy3nVRPlxoWCS-gegtf6fSHkc0q35vmzAA,1542
5
5
  sqladmin/_validators.py,sha256=w0siGhZQq4MD__lu9Edua9DgMOoKET_kk-alpARFHIM,1604
6
6
  sqladmin/ajax.py,sha256=wSP5P9cAIh3GImIc_-E_Mi14aJAcbtiy4_pDPukTs5E,2764
7
- sqladmin/application.py,sha256=7aMILrxNrDxGAM8WX32XxGQbDjGmy6gp0A-tQ1usqsM,27364
8
- sqladmin/authentication.py,sha256=QdN3rLZFU25ihaIIi7iisb55-oFi4GtV_k1xGFvnS6w,2482
7
+ sqladmin/application.py,sha256=4uRwZNbzGjVnlphU1MwRuKBSink5UXbtR1tlkD9XmyU,27827
8
+ sqladmin/authentication.py,sha256=VLNa38rzvQ774c_I1duI5dUVw3-LdcGFyIPafHgXtxg,2665
9
9
  sqladmin/exceptions.py,sha256=6-E8m7rbWE3A7hNaSmB6CVqFzkEuwUpmU5AdGbouPCw,154
10
10
  sqladmin/fields.py,sha256=1CWoVSMr1WkhBJww0-rakx71gRATeIGA6dKgc26z99M,11660
11
+ sqladmin/filters.py,sha256=TJcSR_RnYov6ZeyYYQPHl8oeiJTDmbsebrkmRt9nz5c,11417
11
12
  sqladmin/formatters.py,sha256=K06la0mm9-Bs5UA9L6KGJC_X_lV3UHdJ3ENI6j9j2Zg,480
12
13
  sqladmin/forms.py,sha256=5VhbRWbsG23eDAGz2c03HnED-titNkBdYzDr-TaBSi0,21541
13
- sqladmin/helpers.py,sha256=VTPOFbWkiC1My6MYYyVUCAdg7UmnViiYE2ZigiXx628,8615
14
- sqladmin/models.py,sha256=Ygm5UetuHdn62n1zU5rukNs3dbjypgNC8NfVte9IIXY,40743
14
+ sqladmin/helpers.py,sha256=nSKduAiWhUUKC-eGlURXQwQQzlqAh8X4Bl1AVxoY-DM,8908
15
+ sqladmin/models.py,sha256=dbF80UJYeVNz4s1yyMH_N72PM84zuRjW5WqCfcXYLbE,43529
15
16
  sqladmin/pagination.py,sha256=zg_bAvqZd2Rf0wKJ7uiVfNV9vR0hrsilmi9Ak0SOG_U,2600
16
17
  sqladmin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
18
  sqladmin/templating.py,sha256=o-QMikTrOEgrneLonqCWR3SpAthr-9DoMwOmobM9zq0,2252
18
19
  sqladmin/widgets.py,sha256=xl9tGhj--KTRPmNhFn3WVbvN_tQfkYSNVBGicsFhrgM,3189
19
20
  sqladmin/statics/css/flatpickr.min.css,sha256=GzSkJVLJbxDk36qko2cnawOGiqz_Y8GsQv_jMTUrx1Q,16166
20
21
  sqladmin/statics/css/fontawesome.min.css,sha256=CTSx_A06dm1B063156EVh15m6Y67pAjZZaQc89LLSrU,102217
21
- sqladmin/statics/css/main.css,sha256=XziO3HgOtX6JmGb0lHSNzktBjevR_3XcmqmkV7E9jpc,45
22
+ sqladmin/statics/css/main.css,sha256=BeLxW6X9i_hoGHiXR-AQsdTRi7QPjBG1S2XUo0iFnS4,133
22
23
  sqladmin/statics/css/select2.min.css,sha256=FdatTf20PQr_rWg-cAKfl6j4_IY3oohFAJ7gVC3M34E,14966
23
24
  sqladmin/statics/css/tabler-icons.min.css,sha256=zfxHk87DofHBVVYIurCX27i9Sp-HvSIRAeObJLBdqyg,225500
24
25
  sqladmin/statics/css/tabler-icons.min.css.map,sha256=L2JU7eBUBXadlt31MqbN3ktHqPEg6ZkdkCo3twFFcs0,92491
@@ -34,20 +35,20 @@ sqladmin/statics/webfonts/fa-brands-400.woff2,sha256=-q5vwKqUzFveUHZkfIF6IyBglqH
34
35
  sqladmin/statics/webfonts/fa-regular-400.woff2,sha256=jn5eobFfYqsU29QXaOj7zSHMhZpOpdqBJFfucUKZ-zU,24948
35
36
  sqladmin/statics/webfonts/fa-solid-900.woff2,sha256=cVKmkz7j1pDsKvPQnanXAXI9Fqo0EKbYDyj_iGbzuIA,150124
36
37
  sqladmin/statics/webfonts/tabler-icons.woff2,sha256=26WaCnr1NnLG_uLQ3DMhEkenPiJJsvt_DxjafQUE6sY,837436
37
- sqladmin/templates/sqladmin/_macros.html,sha256=QK--kje7XrH5Flhumf4luLafvTCvTioPMfrsrgTnWEo,2809
38
+ sqladmin/templates/sqladmin/_macros.html,sha256=79GzkgJAaRbzhjm5WIRFkgl8W0U_5hH4gLteQan1rpo,2983
38
39
  sqladmin/templates/sqladmin/base.html,sha256=u6rdmdI6Kg7JteTFmLwh7UhIo2Z1yvZwCNvPnLrHAsg,1783
39
40
  sqladmin/templates/sqladmin/create.html,sha256=Vaj_OHLDIqnZF1HOz_g3ogTaCGZqPEfTJhaxezD1wjM,1396
40
- sqladmin/templates/sqladmin/details.html,sha256=RuWdlsZw5m_gm24Tdn3APNlfKtTHfYw7BnZB0_Tj6Hw,3932
41
+ sqladmin/templates/sqladmin/details.html,sha256=CiH4qAFRl5PaHRWHLwCwABHvk5ghbkTPj51fEt_JQ28,4176
41
42
  sqladmin/templates/sqladmin/edit.html,sha256=geKD5j8ZLcMSciI80-qg_dQM3Sn_7g3_DeIONmSzQt8,1641
42
43
  sqladmin/templates/sqladmin/error.html,sha256=gb-172SMuQKncv0QE8DQdQXeM-fw7oXC0LPLO3ia0IM,290
43
44
  sqladmin/templates/sqladmin/index.html,sha256=vh_IhhYmHPOkdZNrXSEc4e9gXXeZ-nsRBCsJQ_mC7YI,71
44
45
  sqladmin/templates/sqladmin/layout.html,sha256=iBIhypkXp6O3hAHDdMNc4pWd9yxt5mQy7o2lBQD-6Ec,1994
45
- sqladmin/templates/sqladmin/list.html,sha256=OqH4ZtxBWIARJnHqmE9jy58iGH8FgobHlM2XlG4208s,10309
46
+ sqladmin/templates/sqladmin/list.html,sha256=uo5Ns5xx10Ze8hQ-QblArc2hMezDZS_1u0AtBG_BZmk,15912
46
47
  sqladmin/templates/sqladmin/login.html,sha256=Y_hlcIapfVFPNbSIbCe4Tbj5DLLD46emkSlL5-RP4iY,1514
47
48
  sqladmin/templates/sqladmin/modals/delete.html,sha256=jTuv6geT-AhK5HTgRmntrJ8CEi98-kwKrVDrzkOQWhw,1092
48
49
  sqladmin/templates/sqladmin/modals/details_action_confirmation.html,sha256=mN8LJ5OqypxNLAg2_GYZgQmGeK4E6t7JL5RmOEYuliM,1020
49
50
  sqladmin/templates/sqladmin/modals/list_action_confirmation.html,sha256=U52LLNmpLaMuUZSVtGK15oLXsEu6m2S3l9zj9sjN6uM,1078
50
- sqladmin-0.20.1.dist-info/METADATA,sha256=ypbLpPnHwEMZZov5kKz416eplyFOOBwkp1BhWICYHWM,5270
51
- sqladmin-0.20.1.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
52
- sqladmin-0.20.1.dist-info/licenses/LICENSE.md,sha256=4zzpHQMPtND4hzIgJA5qnb4R_wRBWJlYGqNrZolBeP8,1488
53
- sqladmin-0.20.1.dist-info/RECORD,,
51
+ sqladmin-0.22.0.dist-info/METADATA,sha256=-By02GmFg6euFsOK7mixrIxujx9sckUQDkt_IYtKJT4,5342
52
+ sqladmin-0.22.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
53
+ sqladmin-0.22.0.dist-info/licenses/LICENSE.md,sha256=4zzpHQMPtND4hzIgJA5qnb4R_wRBWJlYGqNrZolBeP8,1488
54
+ sqladmin-0.22.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.25.0
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any