如何将Django QuerySet转换为列表

joh*_*ohn 107 django

我有以下内容:

answers = Answer.objects.filter(id__in=[answer.id for answer in answer_set.answers.all()])
Run Code Online (Sandbox Code Playgroud)

然后:

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)
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:

'QuerySet' object has no attribute 'remove'
Run Code Online (Sandbox Code Playgroud)

我已经尝试了各种将QuerySet转换为标准集或列表.什么都行不通.

如何从QuerySet中删除一个项目,以便它不会从数据库中删除它,并且不会返回一个新的QuerySet(因为它在一个不起作用的循环中)?

Zep*_*dio 273

为什么不在查询集上调用list()?

answers_list = list(answers)
Run Code Online (Sandbox Code Playgroud)

这也将评估QuerySet /运行查询.然后,您可以从该列表中删除/添加.

  • 小心这个.当您将其转换为列表时,不同的标志可能会被忽略. (6认同)
  • 如果是这样,则转换为“set”,然后返回“list”以获取唯一的。 (4认同)

Fel*_*ing 39

你可以这样做:

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)
Run Code Online (Sandbox Code Playgroud)

在评估QuerySet时读取,并注意将整个结果加载到内存中是不好的(例如,通过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)
Run Code Online (Sandbox Code Playgroud)


ist*_*ble 33

跟你正在尝试做的事情有点难.您的第一个语句看起来可能是两次获取相同的Answer对象QuerySet.先通过answer_set.answers.all(),然后再通过.filter(id__in=...).仔细检查shell,看看这是否会为您提供所需的答案列表:

answers = answer_set.answers.all()
Run Code Online (Sandbox Code Playgroud)

一旦你清理完了所以对你(以及其他从事代码工作的人)来说,你可能想要查看.exclude()__in 字段查找.

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

new_answers = answers.exclude(question_answer__in=existing_question_answers)
Run Code Online (Sandbox Code Playgroud)

上面的查找可能与您的模型定义不同步,但它可能会让您足够接近自己完成工作.

如果您仍然需要获取id值列表,那么您想要使用.values_list().在您的情况下,您可能希望添加可选的flat = True.

answers.values_list('id', flat=True)
Run Code Online (Sandbox Code Playgroud)

  • 所描述问题的最佳解决方案。我想添加`new_answers = answers.exclude(question_answer__in=existing_question_answers.values_list('id', flat=True))`@istruble (3认同)

Ank*_*ngh 16

通过使用带有step参数的slice运算符,这将导致查询集的评估并创建列表.

list_of_answers = answers[::1]
Run Code Online (Sandbox Code Playgroud)

或者最初你可以做到:

answers = Answer.objects.filter(id__in=[answer.id for answer in
        answer_set.answers.all()])[::1]
Run Code Online (Sandbox Code Playgroud)


小智 13

您可以使用list关键字直接转换.例如:

obj=emp.objects.all()
list1=list(obj)
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,您可以直接将查询集结果转换​​为list.

list是关键字,obj是查询集的结果,并且list1在我们存储转换结果的变量中是变量的list.

  • 但如果你这样做,它就不起作用:`list1 = list(emp.objects.all())` 这似乎违反直觉。 (2认同)

小智 9

使用Pythonlist()函数

列表()。通过调用 list() 来强制评估 QuerySet。例如:

answers = list(answer_set.answers.all())
Run Code Online (Sandbox Code Playgroud)


Piy*_*are 7

为什么不直接调用 .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 上做所有的操作,你为 list 做的。


Sak*_*eer 6

试试这个values_list('column_name', flat=True)

answers = Answer.objects.filter(id__in=[answer.id for answer in answer_set.answers.all()]).values_list('column_name', flat=True)
Run Code Online (Sandbox Code Playgroud)

它将返回一个具有指定列值的列表

  • 小心,我相信这仍然返回一个查询集。[来自文档](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#django.db.models.query.QuerySet.values_list) (6认同)