Skip to content

Commit 0019d9a

Browse files
committed
Fix datetime fields on change page
1 parent 62f4392 commit 0019d9a

12 files changed

Lines changed: 282 additions & 337 deletions

File tree

docs/build.py

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ def read_cls_docstring(cls):
4242

4343
def get_versions():
4444
return [
45+
{
46+
"version": "0.3.6",
47+
"changes": [
48+
"Fix datetime/time handling in transform helpers.",
49+
"Revert get_orm_list method to original implementation. We can use list_select_related and search_fields for prefetch_related_fields and additional_search_fields.",
50+
],
51+
},
4552
{
4653
"version": "0.3.5",
4754
"changes": [
@@ -622,34 +629,6 @@ async def save_model(self, id, payload):
622629
"content": "Model-admin-specific methods and attributes:",
623630
},
624631
{"type": "code-python", "content": inspect.getsource(ModelAdmin)},
625-
{
626-
"type": "text",
627-
"content": "You can customize relation loading and relation search by overriding <code>orm_get_list</code> and forwarding <code>prefetch_related_fields</code> and <code>additional_search_fields</code>:",
628-
},
629-
{
630-
"type": "code-python",
631-
"content": """class TaskAdmin(TortoiseModelAdmin):
632-
search_fields = ("title",)
633-
634-
async def orm_get_list(
635-
self,
636-
offset=None,
637-
limit=None,
638-
search=None,
639-
sort_by=None,
640-
filters=None,
641-
):
642-
return await super().orm_get_list(
643-
offset=offset,
644-
limit=limit,
645-
search=search,
646-
sort_by=sort_by,
647-
filters=filters,
648-
prefetch_related_fields=["user"],
649-
additional_search_fields=["user__email"],
650-
)
651-
""",
652-
},
653632
]
654633
case "#model-form-field-types":
655634
return [

docs/index.html

Lines changed: 49 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ <h4 class="title">FastAdmin</h4>
196196

197197
<ul class="nav flex-column">
198198

199+
<li class="nav-item">
200+
<a class="nav-link" href="#v0_3_6">v0.3.6</a>
201+
</li>
202+
199203
<li class="nav-item">
200204
<a class="nav-link" href="#v0_3_5">v0.3.5</a>
201205
</li>
@@ -327,7 +331,7 @@ <h1>FastAdmin | Documentation</h1>
327331
<div class="row">
328332
<div class="col-sm-6 col-lg-4">
329333
<ul class="list-unstyled">
330-
<li><strong>Version:</strong> 0.3.5</li>
334+
<li><strong>Version:</strong> 0.3.6</li>
331335
<li>
332336
<strong>Author:</strong>
333337
<a href="mailto:vsdudakov@gmail.com" target="_blank">
@@ -344,7 +348,7 @@ <h1>FastAdmin | Documentation</h1>
344348
</li>
345349
<li>
346350
<strong>Updated:</strong>
347-
23 February 2026
351+
24 February 2026
348352
</li>
349353
</ul>
350354
</div>
@@ -2315,8 +2319,6 @@ <h3>Methods and Attributes</h3>
23152319
search: str | None = None,
23162320
sort_by: str | None = None,
23172321
filters: dict | None = None,
2318-
prefetch_related_fields: list[str] | None = None,
2319-
additional_search_fields: list[str] | None = None,
23202322
) -> tuple[list[Any], int]:
23212323
"""This method is used to get list of orm/db model objects.
23222324

@@ -2325,8 +2327,6 @@ <h3>Methods and Attributes</h3>
23252327
:params search: a search query.
23262328
:params sort_by: a sort by field name.
23272329
:params filters: a dict of filters.
2328-
:params prefetch_related_fields: a list of related fields to prefetch.
2329-
:params additional_search_fields: a list of additional search fields.
23302330
:return: A tuple of list of objects and total count.
23312331
"""
23322332
raise NotImplementedError
@@ -2858,64 +2858,6 @@ <h3>Methods and Attributes</h3>
28582858

28592859

28602860

2861-
2862-
<p class="text-4">
2863-
You can customize relation loading and relation search by overriding <code>orm_get_list</code> and forwarding <code>prefetch_related_fields</code> and <code>additional_search_fields</code>:
2864-
</p>
2865-
2866-
2867-
2868-
2869-
2870-
2871-
2872-
2873-
2874-
2875-
2876-
2877-
2878-
2879-
2880-
2881-
2882-
2883-
2884-
2885-
2886-
2887-
2888-
2889-
2890-
<pre>
2891-
<code class="language-python">
2892-
class TaskAdmin(TortoiseModelAdmin):
2893-
search_fields = ("title",)
2894-
2895-
async def orm_get_list(
2896-
self,
2897-
offset=None,
2898-
limit=None,
2899-
search=None,
2900-
sort_by=None,
2901-
filters=None,
2902-
):
2903-
return await super().orm_get_list(
2904-
offset=offset,
2905-
limit=limit,
2906-
search=search,
2907-
sort_by=sort_by,
2908-
filters=filters,
2909-
prefetch_related_fields=["user"],
2910-
additional_search_fields=["user__email"],
2911-
)
2912-
2913-
</code>
2914-
</pre>
2915-
2916-
2917-
2918-
29192861
</section>
29202862

29212863

@@ -3415,6 +3357,49 @@ <h2>Changelog</h2>
34153357

34163358

34173359

3360+
<section id="v0_3_6">
3361+
<h3>v0.3.6</h3>
3362+
3363+
3364+
3365+
<p class="text-4">
3366+
Fix datetime/time handling in transform helpers.
3367+
</p>
3368+
3369+
3370+
3371+
3372+
3373+
3374+
3375+
3376+
3377+
3378+
3379+
3380+
3381+
3382+
3383+
<p class="text-4">
3384+
Revert get_orm_list method to original implementation. We can use list_select_related and search_fields for prefetch_related_fields and additional_search_fields.
3385+
</p>
3386+
3387+
3388+
3389+
3390+
3391+
3392+
3393+
3394+
3395+
3396+
3397+
3398+
3399+
3400+
</section>
3401+
3402+
34183403
<section id="v0_3_5">
34193404
<h3>v0.3.5</h3>
34203405

examples/fastapi_tortoiseorm/example.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,10 @@ class BaseEventModelAdmin(TortoiseModelAdmin):
7575
@register(Event)
7676
class EventModelAdmin(TortoiseModelAdmin):
7777
actions = ("make_is_active", "make_is_not_active")
78-
list_display = ("id", "tournament", "name_with_price", "rating", "event_type", "is_active", "started")
79-
list_filter = ("tournament", "event_type", "is_active")
78+
list_display = ("id", "tournament_name", "name_with_price", "rating", "event_type", "is_active", "started")
79+
list_filter = ("event_type", "is_active")
8080
search_fields = ("name", "tournament__name")
81+
list_select_related = ("tournament",)
8182

8283
@action(description="Make event active")
8384
async def make_is_active(self, ids):
@@ -91,6 +92,11 @@ async def make_is_not_active(self, ids):
9192
async def started(self, obj):
9293
return bool(obj.start_time)
9394

95+
@display
96+
async def tournament_name(self, obj):
97+
tournament = await obj.tournament
98+
return tournament.name
99+
94100
@display()
95101
async def name_with_price(self, obj):
96102
return f"{obj.name} - {obj.price}"

fastadmin/models/base.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@ async def orm_get_list(
248248
search: str | None = None,
249249
sort_by: str | None = None,
250250
filters: dict | None = None,
251-
prefetch_related_fields: list[str] | None = None,
252-
additional_search_fields: list[str] | None = None,
253251
) -> tuple[list[Any], int]:
254252
"""This method is used to get list of orm/db model objects.
255253
@@ -258,8 +256,6 @@ async def orm_get_list(
258256
:params search: a search query.
259257
:params sort_by: a sort by field name.
260258
:params filters: a dict of filters.
261-
:params prefetch_related_fields: a list of related fields to prefetch.
262-
:params additional_search_fields: a list of additional search fields.
263259
:return: A tuple of list of objects and total count.
264260
"""
265261
raise NotImplementedError

fastadmin/models/orms/django.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,6 @@ def orm_get_list(
244244
search: str | None = None,
245245
sort_by: str | None = None,
246246
filters: dict | None = None,
247-
prefetch_related_fields: list[str] | None = None,
248-
additional_search_fields: list[str] | None = None,
249247
) -> tuple[list[Any], int]:
250248
"""This method is used to get list of orm/db model objects.
251249
@@ -254,25 +252,17 @@ def orm_get_list(
254252
:params search: a search query.
255253
:params sort_by: a sort by field name.
256254
:params filters: a dict of filters.
257-
:params prefetch_related_fields: a list of related fields to prefetch.
258-
:params additional_search_fields: a list of additional search fields.
259255
:return: A tuple of list of objects and total count.
260256
"""
261257
qs = self.model_cls.objects.all()
262258

263-
if prefetch_related_fields:
264-
qs = qs.prefetch_related(*prefetch_related_fields)
265-
266259
if filters:
267260
for field_with_condition, value in filters.items():
268261
field = field_with_condition[0]
269262
condition = field_with_condition[1]
270263
qs = qs.filter(**{f"{field}__{condition}" if condition != "exact" else field: value})
271264

272265
search_fields = list(self.search_fields)
273-
if additional_search_fields:
274-
search_fields.extend(additional_search_fields)
275-
276266
if search and search_fields:
277267
search_conditions = [Q(**{f + "__icontains": search}) for f in search_fields]
278268
search_q = search_conditions[0]

fastadmin/models/orms/ponyorm.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,6 @@ def orm_get_list(
224224
search: str | None = None,
225225
sort_by: str | None = None,
226226
filters: dict | None = None,
227-
prefetch_related_fields: list[str] | None = None,
228-
additional_search_fields: list[str] | None = None,
229227
) -> tuple[list[Any], int]:
230228
"""This method is used to get list of orm/db model objects.
231229
@@ -234,8 +232,6 @@ def orm_get_list(
234232
:params search: a search query.
235233
:params sort_by: a sort by field name.
236234
:params filters: a dict of filters.
237-
:params prefetch_related_fields: a list of related fields to prefetch.
238-
:params additional_search_fields: a list of additional search fields.
239235
:return: A tuple of list of objects and total count.
240236
"""
241237

@@ -276,9 +272,6 @@ def orm_get_list(
276272
qs = qs.filter(filter_expr)
277273

278274
search_fields = list(self.search_fields)
279-
if additional_search_fields:
280-
search_fields.extend(additional_search_fields)
281-
282275
if search and search_fields:
283276
ids = []
284277
for search_field in search_fields:
@@ -304,9 +297,6 @@ def orm_get_list(
304297
if self.list_select_related:
305298
qs = qs.prefetch(*[getattr(self.model_cls, field) for field in self.list_select_related])
306299

307-
if prefetch_related_fields:
308-
qs = qs.prefetch(*[getattr(self.model_cls, field) for field in prefetch_related_fields])
309-
310300
if offset is not None and limit is not None:
311301
qs = qs.limit(limit, offset=offset)
312302

fastadmin/models/orms/sqlalchemy.py

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,6 @@ async def orm_get_list(
300300
search: str | None = None,
301301
sort_by: str | None = None,
302302
filters: dict | None = None,
303-
prefetch_related_fields: list[str] | None = None,
304-
additional_search_fields: list[str] | None = None,
305303
) -> tuple[list[Any], int]:
306304
"""This method is used to get list of orm/db model objects.
307305
@@ -310,8 +308,6 @@ async def orm_get_list(
310308
:params search: a search query.
311309
:params sort_by: a sort by field name.
312310
:params filters: a dict of filters.
313-
:params prefetch_related_fields: a list of related fields to prefetch.
314-
:params additional_search_fields: a list of additional search fields.
315311
:return: A tuple of list of objects and total count.
316312
"""
317313

@@ -324,7 +320,6 @@ def convert_sort_by(sort_by: str) -> str:
324320
sessionmaker = self.get_sessionmaker()
325321
async with sessionmaker() as session:
326322
qs = select(self.model_cls)
327-
328323
if filters:
329324
q = []
330325
for field_with_condition, value in filters.items():
@@ -359,9 +354,6 @@ def convert_sort_by(sort_by: str) -> str:
359354
qs = qs.where(and_(*q))
360355

361356
search_fields = list(self.search_fields)
362-
if additional_search_fields:
363-
search_fields.extend(additional_search_fields)
364-
365357
if search and search_fields:
366358
q = []
367359
for field in search_fields:
@@ -385,28 +377,6 @@ def convert_sort_by(sort_by: str) -> str:
385377
for field in self.list_select_related:
386378
qs = qs.options(selectinload(getattr(self.model_cls, field)))
387379

388-
if prefetch_related_fields:
389-
for field_path in prefetch_related_fields:
390-
parts = field_path.split("__")
391-
current_model = self.model_cls
392-
attr = getattr(current_model, parts[0], None)
393-
if attr is None:
394-
continue
395-
option = selectinload(attr)
396-
current_model = getattrs(attr, "property.mapper.class_")
397-
for part in parts[1:]:
398-
if current_model is None:
399-
break
400-
nested_attr = getattr(current_model, part, None)
401-
if nested_attr is None:
402-
break
403-
next_model = getattrs(nested_attr, "property.mapper.class_")
404-
if next_model is None:
405-
break
406-
option = option.selectinload(nested_attr)
407-
current_model = next_model
408-
qs = qs.options(option)
409-
410380
if offset is not None and limit is not None:
411381
qs = qs.offset(offset)
412382
qs = qs.limit(limit)

0 commit comments

Comments
 (0)