如何将 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 转换为列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何将列表转换为queryset django

Django - 如何将 QuerySet 转换为 Q 对象?

如何将此 SQL 转换为 Django QuerySet?

在 Django 中将 QuerySet 转换为 JSON

无法将 Django 查询集转换为列表 [重复]

Django:将带有相关对象的 QuerySet 转换为 JSON