How to convert a Django QuerySet to a list

匿名 (未验证) 提交于 2019-12-03 08:30:34

问题:

I have the following:

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

then later:

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) 

I get an error:

'QuerySet' object has no attribute 'remove' 

I've tried all sorts to convert the QuerySet to a standard set or list. Nothing works.

How can I remove an item from the QuerySet so it doesn't delete it from the database, and doesn't return a new QuerySet (since it's in a loop that won't work)?

回答1:

You could do this:

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) 

Read when QuerySets are evaluated and note that it is not good to load the whole result into memory (e.g. via list()).

Reference: itertools.ifilter

Update with regard to the comment:

There are various ways to do this. One (which is probably not the best one in terms of memory and time) is to do exactly the same :

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) 


回答2:

Why not just call list() on the queryset?

answers_list = list(answers) 

This will also evaluate the QuerySet/run the query. You can then remove/add from that list.



回答3:

It is a little hard to follow what you are really trying to do. Your first statement looks like you may be fetching the same exact QuerySet of Answer objects twice. First via answer_set.answers.all() and then again via .filter(id__in=...). Double check in the shell and see if this will give you the list of answers you are looking for:

answers = answer_set.answers.all() 

Once you have that cleaned up so it is a little easier for you (and others working on the code) to read you might want to look into .exclude() and the __in field lookup.

existing_question_answers = QuestionAnswer.objects.filter(...)  new_answers = answers.exclude(question_answer__in=existing_question_answers) 

The above lookup might not sync up with your model definitions but it will probably get you close enough to finish the job yourself.

If you still need to get a list of id values then you want to play with .values_list(). In your case you will probably want to add the optional flat=True.

answers.values_list('id', flat=True) 


回答4:

By the use of slice operator with step parameter which would cause evaluation of the queryset and create a list.

list_of_answers = answers[::1] 

or initially you could have done:

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


回答5:

Why not just call .values('reqColumn1','reqColumn2') or .values_list('reqColumn1','reqColumn2') on the queryset?

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

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

OR

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

result = [(value1,value2)]

You can able to do all the operation on this QuerySet, which you do for list .



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!