Проблема с получением экземпляров модели в определенном порядке
У меня есть список паспортных данных пользователей. Мне нужно получить набор запросов пользователей в той же последовательности, в которой их паспортные данные упорядочены в списке. Вот список с паспортными данными:
lst = ['AA1111111', 'AD2222222', 'AA3333333', 'AA4444444', 'АВ5555555']
Я пытался сделать что-то вроде этого:
empty_queryset = Users.objects.none()
for passport_number in lst:
user = Users.objects.filter(passport_number__exact=passport_number)
empty_queryset |= user
Я ожидал этого:
<QuerySet [<Users: AA1111111>, <Users: AD2222222>, <Users: AA3333333>, <Users: AA4444444>, <Users: АВ5555555>]>
Но это происходило в хаотичном порядке:
<QuerySet [<Users: АВ5555555>, <Users: AA1111111>, <Users: AD2222222>, <Users: AA3333333>, <Users: AA4444444>]>
Тогда я попробовал следующее:
Users.objects.filter(passport_number__in=[i for i in lst])
Но все равно не работает
Можете ли вы попробовать это?
from yourapp.models import User
lst = ['AA1111111', 'AD2222222', 'AA3333333', 'AA4444444', 'АВ5555555']
users_queryset = User.objects.filter(passport_number__in=lst)
users_list = sorted(users_queryset, key=lambda x:lst.index(x.passport_number))
Оба по сути делают одно и то же, составляя запрос, который выглядит так:
SELECT *
FROM users
WHERE passport_number IN ('AA1111111',
'AD2222222',
'AA3333333',
'AA4444444',
'АВ5555555')
<<<Поскольку нет условия , база ORDER BY
данных может представить данные в любом порядке. Обычно, если задействованы индексы, данные могут быть упорядочены как индекс, но это скорее деталь реализации.
Вы можете работать с .union(…)
[Django-doc] для работы с:
SELECT *
FROM users
WHERE passport_number = 'AA1111111'
UNION
SELECT *
FROM users
WHERE passport_number = 'AD2222222'
-- …
тогда это выглядит так:
Users.objects.none().union(
*[User.objects.filter(passport_number=p) for p in lst], all=True
)
Другим вариантом может быть сортировка элементов на уровне Django/Python с помощью:
lst = ['AA1111111', 'AD2222222', 'AA3333333', 'AA4444444', 'АВ5555555']
order = {k: i for i, k in enumerate(lst)}
items = sorted(
Users.objects.filter(passport_number__in=lst),
key=lambda x: order.get(x.passport_number),
)
но тогда это будет список из Users
, а не QuerySet
, поэтому дополнительная фильтрация, пагинация и т.д. не может быть выполнена через QuerySet
API.
Note: Normally a Django model is given a singular name [django-antipatterns], so
User
instead of.Users