【问题标题】:How to convert a Django QuerySet to a list?如何将 Django QuerySet 转换为列表?
【发布时间】: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(因为它处于一个不起作用的循环中)?

【问题讨论】:

    标签: django


    【解决方案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() 用于删除

          【讨论】:

            猜你喜欢
            • 2013-09-07
            • 2011-12-10
            • 2012-03-08
            • 1970-01-01
            • 2011-03-14
            • 2017-09-17
            • 2012-07-26
            • 1970-01-01
            • 2013-05-25
            相关资源
            最近更新 更多