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.
- sqladmin/__init__.py +1 -1
- sqladmin/_menu.py +1 -1
- sqladmin/_types.py +49 -1
- sqladmin/application.py +22 -8
- sqladmin/authentication.py +6 -2
- sqladmin/filters.py +340 -0
- sqladmin/helpers.py +12 -4
- sqladmin/models.py +89 -14
- sqladmin/statics/css/main.css +8 -1
- sqladmin/templates/sqladmin/_macros.html +5 -2
- sqladmin/templates/sqladmin/details.html +5 -1
- sqladmin/templates/sqladmin/list.html +274 -197
- {sqladmin-0.20.1.dist-info → sqladmin-0.22.0.dist-info}/METADATA +7 -6
- {sqladmin-0.20.1.dist-info → sqladmin-0.22.0.dist-info}/RECORD +16 -15
- {sqladmin-0.20.1.dist-info → sqladmin-0.22.0.dist-info}/WHEEL +1 -1
- {sqladmin-0.20.1.dist-info → sqladmin-0.22.0.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -1,208 +1,285 @@
|
|
|
1
1
|
{% extends "sqladmin/layout.html" %}
|
|
2
2
|
{% block content %}
|
|
3
|
-
<div class="
|
|
4
|
-
<div class="
|
|
5
|
-
<div class="
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class="
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
{%
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
</
|
|
150
|
-
|
|
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.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: sqladmin
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.22.0
|
|
4
4
|
Summary: SQLAlchemy admin for FastAPI and Starlette
|
|
5
|
-
Project-URL: Documentation, https://aminalaee.
|
|
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.
|
|
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.
|
|
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=
|
|
2
|
-
sqladmin/_menu.py,sha256=
|
|
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=
|
|
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=
|
|
8
|
-
sqladmin/authentication.py,sha256=
|
|
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=
|
|
14
|
-
sqladmin/models.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
51
|
-
sqladmin-0.
|
|
52
|
-
sqladmin-0.
|
|
53
|
-
sqladmin-0.
|
|
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,,
|
|
File without changes
|