170

How can I convert a Django QuerySet into a list of dicts? I haven't found an answer to this so I'm wondering if I'm missing some sort of common helper function that everyone uses.

Mridang Agarwalla
  • 40,471
  • 69
  • 211
  • 366

11 Answers11

252

Use the .values() method:

>>> Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]

Note: the result is a QuerySet which mostly behaves like a list, but isn't actually an instance of list. Use list(Blog.objects.values(…)) if you really need an instance of list.

David Wolever
  • 139,281
  • 83
  • 327
  • 490
  • 7
    yes you specify which fields you want `values()` to return by passing them in as arguments. Also be careful although it looks like values returns a list of dicts its actually a `` and not a list. – dm03514 Oct 18 '11 at 18:31
  • 15
    this doesn't actually return a list though – astreltsov Jan 25 '17 at 03:26
  • also, you cant get the results of instance methods of your object with `values()`, I don't know if there is a good method to do the same as `values()` but also with calling the instance methods?! – Asara Oct 06 '18 at 21:55
  • This is very hard to understand. What is *Blog* and what is *object*? It would be good to see the data types of each. For example, which is the QuerySet? – Anthony Nash May 28 '21 at 09:39
35

The .values() method will return you a result of type ValuesQuerySet which is typically what you need in most cases.

But if you wish, you could turn ValuesQuerySet into a native Python list using Python list comprehension as illustrated in the example below.

result = Blog.objects.values()             # return ValuesQuerySet object
list_result = [entry for entry in result]  # converts ValuesQuerySet into Python list
return list_result

I find the above helps if you are writing unit tests and need to assert that the expected return value of a function matches the actual return value, in which case both expected_result and actual_result must be of the same type (e.g. dictionary).

actual_result = some_function()
expected_result = {
    # dictionary content here ...
}
assert expected_result == actual_result
Arthur Rimbun
  • 3,443
  • 2
  • 15
  • 15
17

If you need native data types for some reason (e.g. JSON serialization) this is my quick 'n' dirty way to do it:

data = [{'id': blog.pk, 'name': blog.name} for blog in blogs]

As you can see building the dict inside the list is not really DRY so if somebody knows a better way ...

Semmel
  • 2,279
  • 2
  • 19
  • 29
  • I seem to have got it working with `data = list( blogs )` and then `json.dumps( data )`. An array comes out with a bunch of objects on the javascript side, no parsing needed. – Arthur Tarasov Oct 18 '19 at 05:58
6

Type Cast to List

    job_reports = JobReport.objects.filter(job_id=job_id, status=1).values('id', 'name')

    json.dumps(list(job_reports))
Saurabh Chandra Patel
  • 11,619
  • 5
  • 84
  • 76
3

You need DjangoJSONEncoder and list to make your Queryset to json, ref: Python JSON serialize a Decimal object

import json
from django.core.serializers.json import DjangoJSONEncoder


blog = Blog.objects.all().values()
json.dumps(list(blog), cls=DjangoJSONEncoder)
gaozhidf
  • 2,241
  • 1
  • 19
  • 15
3

You do not exactly define what the dictionaries should look like, but most likely you are referring to QuerySet.values(). From the official django documentation:

Returns a ValuesQuerySet — a QuerySet subclass that returns dictionaries when used as an iterable, rather than model-instance objects.

Each of those dictionaries represents an object, with the keys corresponding to the attribute names of model objects.

Bernhard Vallant
  • 46,415
  • 18
  • 114
  • 143
2

You can use the values() method on the dict you got from the Django model field you make the queries on and then you can easily access each field by a index value.

Call it like this -

myList = dictOfSomeData.values()
itemNumberThree = myList[2] #If there's a value in that index off course...
Ido Magor
  • 544
  • 1
  • 5
  • 13
1

You could define a function using model_to_dict as follows:

def queryset_to_list(qs,fields=None, exclude=None):
    my_list=[]
    for x in qs:
        my_list.append(model_to_dict(x,fields=fields,exclude=exclude))
    return my_list

Suppose your Model has following fields

id
name
email

Run following commands in django shell

>>>qs=<yourmodel>.objects.all()
>>>list=queryset_to_dict(qs)
>>>list
[{'id':1, 'name':'abc', 'email':'abc@ab.co'},{'id':2, 'name':'xyz', 'email':'xy@xy.co'}]

Say you want only id and name in the list of queryset dictionary

>>>qs=<yourmodel>.objects.all()
>>>list=queryset_to_dict(qs,fields=['id','name'])
>>>list
[{'id':1, 'name':'abc'},{'id':2, 'name':'xyz'}]

Similarly you can exclude fields in your output.

ABN
  • 686
  • 9
  • 22
0

If you already have a query set you just use the list function to turn it into a list of dicts, eg:

list(MyModel.objects.values())

Mark B
  • 458
  • 5
  • 6
-1

im a newbie in python and i love @David Wolever answer

user = Blog.objects.all()
user = list(user.values("username", "id"))

in my case i use this to print username

user = Blog.objects.all()
user = list(user.values("username"))
name = []
for i in user:
    name.append(i["username"])
print(name)
# ["joe", "karen", "stuf"]
BitchBark
  • 7
  • 1
-2

Simply put list(yourQuerySet).

Miguel de Matos
  • 904
  • 2
  • 11
  • 18