2010-12-12 21 views
67

我有以下几点:如何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(因为它在循环中不起作用)?

回答

26

你可以这样做:

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) 
+0

我在上面的代码示例中添加了一行,从exising_question_answers删除了相同的条目。有没有可能为此使用ifilter? – john 2010-12-12 22:43:33

+0

我会将此标记为正确的,因为我不知道过滤器并忘记了有关lambda表达式。 – john 2010-12-13 20:10:13

194

为什么不直接调用queryset上的list()?

answers_list = list(answers) 

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

+3

我试过了。由于某种原因不起作用。 – john 2010-12-12 22:33:49

+0

当我试过这个,我得到了同样的错误。任何人都可以解释为什么在queryset上调用list()仍然使它作为一个查询集进行评估(因此没有'remove()'方法)? – john 2010-12-12 22:46:03

+0

@john,这应该没有问题。你可以使用'list()'发布代码,你尝试过并且不工作吗? – Agos 2010-12-12 23:05:07

22

这是一个有点难以跟随你真正要做的。您的第一条语句看起来像您可能会两次提取同一个确切的Answer对象。先通过answer_set.answers.all(),然后再通过.filter(id__in=...)。在外壳仔细检查,看看这会给你答案的,你正在寻找的名单:

answers = answer_set.answers.all() 

一旦你的清理所以它是很容易就能为你(和其他人的代码工作)阅读你可能想看看.exclude()__infield 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) 
+0

感谢您的回答。不幸的是,我没有提供足够的细节来证明我无法使用您的方法。 – john 2010-12-13 20:11:32

+0

描述问题的最佳解决方案。我想添加'new_answers = answers.exclude(question_answer__in = existing_question_answers.values_list('id',flat = True))'@istruble – 2016-04-28 13:45:29

7

通过使用带有步骤参数的切片运算符会导致查询集评估并创建一个列表。

list_of_answers = answers[::1] 

或最初你可以做:

answers = Answer.objects.filter(id__in=[answer.id for answer in 
     answer_set.answers.all()])[::1] 
+0

据我所知,django queryset不支持负向索引。 – 2016-08-30 07:21:41

+0

好的阿列克谢。你就在这里。我已经更新了答案。 – 2016-08-31 16:37:14

2

为什么不呼吁查询集 .values('reqColumn1','reqColumn2').values_list('reqColumn1','reqColumn2')

answers_list = models.objects.values('reqColumn1','reqColumn2')

result = [{'reqColumn1':value1,'reqColumn2':value2}]

OR

answers_list = models.objects.values_list('reqColumn1','reqColumn2')

result = [(value1,value2)]

你可以做到这个查询集,它为你做列表所有操作。