如何将 Django QuerySet 转换为列表?
Posted
技术标签:
【中文标题】如何将 Django QuerySet 转换为列表?【英文标题】:How to convert a Django QuerySet to a list? 【发布时间】:2011-05-24 09:23:46 【问题描述】:我有以下几点:
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】:为什么不直接在Queryset
上致电list()
?
answers_list = list(answers)
这也将评估QuerySet
/运行查询。然后,您可以从该列表中删除/添加。
【讨论】:
小心这个。当您将其转换为列表时,不同的标志可能会被忽略。 我可以独立完成,但我可以在 django 形式的查询集中完成。知道为什么吗? 如果是这样,则转换为set
,然后返回list
以获取唯一的。
@rh0dium - 你对此有什么参考吗?我在我的代码中使用它,我发现很难理解它如何影响唯一性(不是说它不会 - 只是我无法连接这些点)。【参考方案2】:
你可以这样做:
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)
阅读when QuerySets are evaluated并注意将整个结果加载到内存中是不好的(例如通过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)
【讨论】:
我在上面的代码示例中又添加了一行,从 exising_question_answers 中删除了相同的条目。是否有可能以某种方式使用 ifilter? 我会将其标记为正确,因为我不知道过滤器并且忘记了 lambdas。【参考方案3】:要遵循您真正想做的事情有点困难。您的第一条语句看起来可能两次获取相同的确切 QuerySet 的 Answer 对象。首先通过answer_set.answers.all()
,然后再次通过.filter(id__in=...)
。仔细检查 shell,看看这是否会为您提供您正在寻找的答案列表:
answers = answer_set.answers.all()
一旦你把它清理干净,这样你(和其他处理代码的人)会更容易阅读,你可能想要查看.exclude() 和__in field lookup。
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)
【讨论】:
感谢您的回答。不幸的是,我没有提供足够的细节来表明我不能使用你的方法。 所描述问题的最佳解决方案。我要添加new_answers = answers.exclude(question_answer__in=existing_question_answers.values_list('id', flat=True))
@istruble
values_list() 是最好的选择。【参考方案4】:
通过使用带有 step 参数的切片运算符,这将导致对查询集进行评估并创建一个列表。
list_of_answers = answers[::1]
或者最初你可以这样做:
answers = Answer.objects.filter(id__in=[answer.id for answer in
answer_set.answers.all()])[::1]
【讨论】:
据我所知,django queryset 不支持负索引。 好的,阿列克谢。你就在这里。我已经更新了答案。【参考方案5】:您可以使用list
关键字直接进行转换。
例如:
obj=emp.objects.all()
list1=list(obj)
使用上面的代码可以直接将查询集结果转换成
list
。
这里list
是关键字,obj
是查询集的结果,list1
是该变量中的变量,我们将转换后的结果存储在list
中。
【讨论】:
但是如果你这样做它不起作用:list1 = list(emp.objects.all())
这似乎违反直觉。【参考方案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)
它将返回一个包含指定列值的列表
【讨论】:
【参考方案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 执行的操作一样。
【讨论】:
【参考方案8】:使用pythonlist()
函数
列表()。通过在其上调用 list() 来强制评估 QuerySet。为了 示例:
answers = list(answer_set.answers.all())
【讨论】:
请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。【参考方案9】:def querySet_to_list(qs):
"""
this will return python list<dict>
"""
return [dict(q) for q in qs]
def get_answer_by_something(request):
ss = Answer.objects.filter(something).values()
querySet_to_list(ss) # python list return.(json-able)
此代码将 django 查询集转换为 python 列表
【讨论】:
【参考方案10】:您可以使用exclude()
函数代替remove()
从查询集中删除对象。
它的语法类似于filter()
例如:-
qs = qs.exclude(id= 1)
在上面的代码中,它会从 qs 中删除所有 id 为 '1' 的对象
其他信息:-
filter()
用于选择特定对象,exclude()
用于删除
【讨论】:
以上是关于如何将 Django QuerySet 转换为列表?的主要内容,如果未能解决你的问题,请参考以下文章