Пользовательский заказ Django QuerySet по идентификатору
Учитывая список идентификаторов /pks, я хотел бы сгенерировать объект QuerySet
объектов, упорядоченных по индексу в списке.
Обычно я начинал с:
pk_list = [5, 9, 2, 14]
queryset = MyModel.objects.filter(pk__in=pk_list)
Это, конечно, возвращает объекты, но в порядке свойств метаопределения моделей, и я хочу получить записи в порядке pk
в pk_list
.
Конечным результатом должен быть один объект QuerySet
(а не список), поскольку я хочу передать упорядоченное поле формы QuerySet
в Django ModelMultipleChoiceField
.
Ответы
Ответ 1
Существует не встроенный способ сделать это.
Если вы используете MySQL, вы можете использовать эту базу данных FIELD()
для настройки пользовательской последовательности упорядочения на вашей модели и сортировки по ней. Это будет работать:
pk_list = [5, 9, 2, 14]
ordering = 'FIELD(`id`, %s)' % ','.join(str(id) for id in pk_list)
queryset = MyModel.objects.filter(pk__in=[pk_list]).extra(
select={'ordering': ordering}, order_by=('ordering',))
Ответ 2
Я не знаю, как это сделать, используя условие фильтра. Если ваша база данных вернет строки в порядке предложения IN
, тогда вы сможете комбинировать метод Django extra
с ROWNUM
, предоставленный вашей базой данных, чтобы достичь этого.
Например,
queryset = MyModel.objects.filter(pk__in=[pk_list]).extra(
select: {'rownum': 'row_num()'}).order_by('rownum')
Где row_num()
предполагается функцией базы данных, которая возвращает номер строки текущей строки. Postgresql 8.4+ поддерживает row_num()
, но я не знаю, как упорядочить строки, возвращенные с использованием того же порядка, что и значения в предложении IN
.
Я думаю, что лучший способ был бы для подкласса ModelMultipleChoiceField
и добавления пользовательской логики сортировки при рендеринге.