How to convert a Django QuerySet to a list?

Django

Django Problem Overview


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)?

Django Solutions


Solution 1 - Django

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.

Solution 2 - Django

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)

Solution 3 - Django

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)

Solution 4 - Django

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]

Solution 5 - Django

You can directly convert using the list keyword. For example:

obj=emp.objects.all()
list1=list(obj)

> Using the above code you can directly convert a query set result into a list.

Here list is keyword and obj is result of query set and list1 is variable in that variable we are storing the converted result which in list.

Solution 6 - Django

Try this 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)

It will return you a list with specified column values

Solution 7 - Django

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 .

Solution 8 - Django

Use python list() function

> list(). Force evaluation of a QuerySet by calling list() on it. For > example:

answers = list(answer_set.answers.all())

Solution 9 - Django

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)
    

this code convert django queryset to python list

Solution 10 - Django

instead of remove() you can use exclude() function to remove an object from the queryset. it's syntax is similar to filter()

eg : -

qs = qs.exclude(id= 1)

in above code it removes all objects from qs with id '1'

additional info :-

filter() used to select specific objects but exclude() used to remove

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjohnView Question on Stackoverflow
Solution 1 - DjangoZeppomedioView Answer on Stackoverflow
Solution 2 - DjangoFelix KlingView Answer on Stackoverflow
Solution 3 - DjangoistrubleView Answer on Stackoverflow
Solution 4 - DjangoAnkit SinghView Answer on Stackoverflow
Solution 5 - Djangopatel shahrukhView Answer on Stackoverflow
Solution 6 - DjangoSakeerView Answer on Stackoverflow
Solution 7 - DjangoPiyush S. WanareView Answer on Stackoverflow
Solution 8 - DjangoHamed BakhtiView Answer on Stackoverflow
Solution 9 - DjangoEunSeong LeeView Answer on Stackoverflow
Solution 10 - DjangoMuhammed Faes EPView Answer on Stackoverflow