Comment convertir un Django QuerySet en liste de dictionnaires?

122

Comment puis-je convertir un Django QuerySet en une liste de dictionnaires? Je n'ai pas trouvé de réponse à cela, alors je me demande s'il me manque une sorte de fonction d'assistance commune que tout le monde utilise.

Mridang Agarwalla
la source

Réponses:

178

Utilisez la .values()méthode:

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

Remarque: le résultat est un QuerySetqui se comporte principalement comme une liste, mais n'est pas en fait une instance de list. À utiliser list(Blog.objects.values(…))si vous avez vraiment besoin d'une instance de list.

David Wolever
la source
7
oui, vous spécifiez les champs que vous souhaitez values()renvoyer en les transmettant comme arguments. Faites également attention bien que cela ressemble à des valeurs qui renvoie une liste de dictionnaires, c'est en fait un a <class 'django.db.models.query.ValuesQuerySet'>et non une liste.
dm03514
10
cela ne renvoie pas réellement une liste
astreltsov
aussi, vous ne pouvez pas obtenir les résultats des méthodes d'instance de votre objet avec values(), je ne sais pas s'il existe une bonne méthode pour faire la même chose que values()mais aussi avec l'appel des méthodes d'instance?!
Asara
34

La .values()méthode vous renverra un résultat de type ValuesQuerySetqui est généralement ce dont vous avez besoin dans la plupart des cas.

Mais si vous le souhaitez, vous pouvez vous transformer ValuesQuerySeten une liste Python native en utilisant la compréhension de liste Python comme illustré dans l'exemple ci-dessous.

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

Je trouve que ce qui précède aide si vous écrivez des tests unitaires et devez affirmer que la valeur de retour attendue d'une fonction correspond à la valeur de retour réelle, auquel cas les deux expected_resultet actual_resultdoivent être du même type (par exemple, dictionnaire).

actual_result = some_function()
expected_result = {
    # dictionary content here ...
}
assert expected_result == actual_result
Arthur Rimbun
la source
17
Ou vous pouvez simplifier la conversion en liste avec cecilist(result)
Adiyat Mubarak
12

Si vous avez besoin de types de données natifs pour une raison quelconque (par exemple, la sérialisation JSON), c'est ma façon rapide et sale de le faire:

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

Comme vous pouvez le voir, construire le dict à l'intérieur de la liste n'est pas vraiment SEC, donc si quelqu'un connaît un meilleur moyen ...

Semmel
la source
Je semble l'avoir fait fonctionner avec data = list( blogs )et ensuite json.dumps( data ). Un tableau sort avec un tas d'objets du côté javascript, aucune analyse nécessaire.
Arthur Tarasov
3

Vous ne définissez pas exactement à quoi devraient ressembler les dictionnaires, mais vous faites très probablement référence QuerySet.values(). De la documentation officielle de django :

Renvoie a ValuesQuerySet- une QuerySetsous-classe qui renvoie des dictionnaires lorsqu'elle est utilisée comme une itération, plutôt que comme des objets d'instance de modèle.

Chacun de ces dictionnaires représente un objet, les clés correspondant aux noms d'attributs des objets modèles.

Bernhard Vallant
la source
2

Tapez 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
la source
1

Vous pouvez utiliser la values()méthode sur le dict que vous avez obtenu à partir du champ de modèle Django sur lequel vous effectuez les requêtes, puis vous pouvez facilement accéder à chaque champ par une valeur d'index.

Appelez ça comme ça -

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

Vous avez besoin DjangoJSONEncoderet listpour rendre votre Querysetto json, ref: Python JSON sérialise un objet Decimal

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


blog = Blog.objects.all().values()
json.dumps(list(blog), cls=DjangoJSONEncoder)
gaozhidf
la source
0

En termes simples list(yourQuerySet).

Miguel de Matos
la source
2
Cela vous donne une liste d'objets, pas une liste de dictionnaires.
Flimm
0

Vous pouvez définir une fonction en utilisant model_to_dict comme suit:

def queryset_to_dict(qs,fields=None, exclude=None):
    my_array=[]
    for x in qs:
        my_array.append(model_to_dict(x,fields=fields,exclude=exclude))
    return my_array
ABN
la source