Как преобразовать 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, которую вы делаете для списка.