Вопрос по python, sorting, list – django - преобразовать список обратно в набор запросов [duplicate]

50

This question already has an answer here:

A QuerySet by aggregate field value 3 answers

У меня есть несколько записей, которые я хотел бы отсортировать на основе вычисленного значения. Получил ответздесь... вот так:

sorted(Profile.objects.all(), key=lambda p: p.reputation)

в классе профиля, как это:

class Profile(models.Model):

    ...

    @property
    def reputation(self):
        ...

К сожалению, универсальное представление ожидает объект queryset и выдает ошибку, если я дам ему список.

Is there a way to do this that returns a queryset

или же...

Can I convert a list to a queryset somehow? Не могу найти ничего подобного в документации Django.

Я надеюсь не денормализовать данные, но, думаю, сделаю это, если придется.

Update / Answer:

кажется, что единственный способ вернуть набор запросов - это если вы можете передать всю свою логику в SQL-запросы.

Когда это невозможно, (я думаю) вам нужно денормализовать данные

моды, это не дубликат Это другой вопрос, на который дан ответ: «Вы не можете этого сделать, поэтому вы должны сделать что-то другое». Это "что-то еще" описано в другом вопросе. Jiaaro
Разве это не лучший вопрос? Как передать список (или словарь) в общий вид ?? Я предполагаю, что если вы решите это, тогда не будет иметь значения, сделали ли вы это путем преобразования в набор запросов или нет ... Andy Baker
да ... это так, но я просто хотел узнать, есть ли простой способ преобразовать его в набор запросов, прежде чем я разберусь с общими представлениями;) Jiaaro

Ваш Ответ

2   ответа
21

оса никогда не содержит данных; это просто представляет запрос к базе данных. Если бы вы создали свой список для запроса, ему пришлось бы снова получать все, и это было бы излишним и очень плохим по производительности.

Что ты можешь сделать:

Describe how the reputation field is calculated; it's probably possible to order the data in the database somehow. Modify the view to not require a query object. If it needs to do additional filtering etc. this should be done before any ordering, since the ordering will take less time with less entries (and less data will be fetched from the database.) So you could send the filtered query object to the sort function just before you send it to the template (which shouldn't care whether it's a query or a list.)
В таком случае вам следует либо сохранить его в виде поля (избыточные данные не всегда плохи, если это помогает повысить производительность, даже в нормализованных базах данных), либо вы должны упорядочить что-то еще. Я предполагаю, что это вычисляемое или объединенное поле, и вы также можете сортировать по ним с помощью модели базы данных Django.
только что пришла идея ... так как универсальный вид хочет выполнить какую-то фильтрацию, почему я не делаю сортировку с тегом шаблона? Jiaaro
Это необходимо сделать, если вам нужно предоставить QuerySet для Django REST, django-graphene, paginators или любого другого API, для которого требуется QuerySet. Список объектов может поступать из кэша или фильтроваться и сортироваться в python (не в БД). Мы должны просто написать что-то, что берет список и крякает, как QuerySet.
Если у вас нет доступа к представлению, и вы не можете обернуть его или каким-либо другим образом повлиять на набор запросов перед его отправкой в шаблон, то это, безусловно, альтернатива. Я не знаю, реализован ли фильтр dictsort для поддержки экземпляров модели, но если это не так, вы всегда можете сделать свой собственный.
репутация это свойство, а не поле ... так что это недействительно Jiaaro
83

НО, что вы можете сделать, это получить всеids объектов в вашем списке, затем выполнитеmodel.objects.filter(pk__in=list_of_ids)

Недостатком этого является то, что он не будет сохранять первоначальный порядок
Это очень медленно для больших коллекций, но было ценно в ограниченной ситуации, в которой я нуждался в этом, чтобы быстро решить проблему. Это позволяет использовать методы QuerySet в списках объектов, что может быть удобно для сжатого кода.
Это хорошо сработало для быстрого прототипа, но я, конечно, не рекомендую делать это в производстве по причинам, указанным @Blixt.

Похожие вопросы