Как преобразовать QuerySet Django в список

У меня есть следующее:

answers = Answer.objects.filter(id__in=[answer.id for answer in answer_set.answers.all()])

а затем:

for i in range(len(answers)):
    # iterate through all existing QuestionAnswer objects
    for existing_question_answer in existing_question_answers:
        # if an answer is already associated, remove it from the
        # list of answers to save
        if answers[i].id == existing_question_answer.answer.id:
            answers.remove(answers[i])           # doesn't work
            existing_question_answers.remove(existing_question_answer)

Я получаю сообщение об ошибке:

'QuerySet' object has no attribute 'remove'

Я пробовал все виды конвертировать QuerySet в стандартный набор или список. Ничего не работает.

Как я могу удалить элемент из QuerySet, чтобы он не удалял его из базы данных и не возвращал новый QuerySet (поскольку он в цикле, который не будет работать)?

Ответ 1

Вы можете сделать это:

import itertools

ids = set(existing_answer.answer.id for existing_answer in existing_question_answers)
answers = itertools.ifilter(lambda x: x.id not in ids, answers)

Прочитайте когда QuerySets оцениваются, и обратите внимание, что это нехорошо загружать весь результат в память (например, через list()).

Ссылка: itertools.ifilter

Обновить в отношении комментария:

Существуют различные способы сделать это. Один (который, вероятно, не самый лучший в плане памяти и времени) должен делать то же самое:

answer_ids = set(answer.id for answer in answers)
existing_question_answers = filter(lambda x: x.answer.id not in answers_id, existing_question_answers)

Ответ 2

Почему бы не просто вызвать список() в запросе?

answers_list = list(answers)

Это также оценит QuerySet/запустит запрос. Затем вы можете удалить/добавить из этого списка.

Ответ 3

Немного трудно следить за тем, что вы действительно пытаетесь сделать. Ваш первый оператор выглядит так, что вы можете дважды получать один и тот же объект QuerySet of Answer. Сначала через answer_set.answers.all(), а затем снова через .filter(id__in=...). Двойная проверка в оболочке и посмотрите, даст ли это вам список ответов, которые вы ищете:

answers = answer_set.answers.all()

После того, как вы очистите его, вам будет легче (и другим, работающим над кодом) читать вам, возможно, вы захотите изучить . exclude() и __ в поиск в поле.

existing_question_answers = QuestionAnswer.objects.filter(...)

new_answers = answers.exclude(question_answer__in=existing_question_answers)

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

Если вам все еще нужно получить список значений id, то вы хотите играть с . values_list(). В вашем случае вы, вероятно, захотите добавить опцию flat = True.

answers.values_list('id', flat=True)

Ответ 4

Используя оператор slice с параметром шага, который вызовет оценку запроса и создаст список.

list_of_answers = answers[::1]

или изначально вы могли бы сделать:

answers = Answer.objects.filter(id__in=[answer.id for answer in
        answer_set.answers.all()])[::1]

Ответ 5

Почему бы просто не позвонить .values('reqColumn1','reqColumn2') или .values_list('reqColumn1','reqColumn2') в запросе?

answers_list = models.objects.values('reqColumn1','reqColumn2')

result = [{'reqColumn1':value1,'reqColumn2':value2}]

ИЛИ

answers_list = models.objects.values_list('reqColumn1','reqColumn2')

result = [(value1,value2)]

Вы можете выполнить всю операцию над этим QuerySet, которую вы делаете для списка.