¿Cómo convierto un QuerySet de Django en una lista de dictados?

122

¿Cómo puedo convertir un Django QuerySet en una lista de dictados? No he encontrado una respuesta a esto, así que me pregunto si me falta algún tipo de función auxiliar común que todos usan.

Mridang Agarwalla
fuente

Respuestas:

178

Usa el .values()método:

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

Nota: el resultado es un QuerySetque se comporta principalmente como una lista, pero en realidad no es una instancia de list. Úselo list(Blog.objects.values(…))si realmente necesita una instancia de list.

David Wolever
fuente
7
sí, especifica los campos que desea values()devolver pasándolos como argumentos. También tenga cuidado, aunque parece que los valores devuelven una lista de dictados, en realidad es una <class 'django.db.models.query.ValuesQuerySet'>y no una lista.
dm03514
10
Sin embargo, esto en realidad no devuelve una lista
astreltsov
Además, no puede obtener los resultados de los métodos de instancia de su objeto con values(), no sé si hay un buen método para hacer lo mismo values()pero también para llamar a los métodos de instancia.
Asara
34

El .values()método le devolverá un resultado de tipo ValuesQuerySetque normalmente es lo que necesita en la mayoría de los casos.

Pero si lo desea, puede convertirlo ValuesQuerySeten una lista nativa de Python usando la comprensión de la lista de Python como se ilustra en el siguiente ejemplo.

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

Me parece que el anterior ayuda si está escribiendo pruebas unitarias y necesidad de afirmar que el valor de retorno esperado de una función coincide con el valor de retorno real, en cuyo caso tanto expected_resulty actual_resultdeben ser del mismo tipo (por ejemplo, el diccionario).

actual_result = some_function()
expected_result = {
    # dictionary content here ...
}
assert expected_result == actual_result
Arthur Rimbun
fuente
17
O puede simplificar la conversión a la lista con estolist(result)
Adiyat Mubarak
12

Si necesita tipos de datos nativos por alguna razón (por ejemplo, serialización JSON), esta es mi forma rápida y sucia de hacerlo:

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

Como puede ver, construir el dict dentro de la lista no es realmente SECO, por lo que si alguien conoce una manera mejor ...

Semmel
fuente
Parece que lo tengo funcionando con data = list( blogs )y luego json.dumps( data ). Aparece una matriz con un montón de objetos en el lado de JavaScript, sin necesidad de análisis.
Arthur Tarasov
3

No define exactamente cómo deberían verse los diccionarios, pero lo más probable es que se esté refiriendo QuerySet.values(). De la documentación oficial de django :

Devuelve una ValuesQuerySet: una QuerySetsubclase que devuelve diccionarios cuando se usa como iterable, en lugar de objetos de instancia de modelo.

Cada uno de esos diccionarios representa un objeto, con las claves correspondientes a los nombres de los atributos de los objetos modelo.

Bernhard Vallant
fuente
2

Escriba 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
fuente
1

Puede usar el values()método en el diccionario que obtuvo del campo del modelo de Django en el que realiza las consultas y luego puede acceder fácilmente a cada campo mediante un valor de índice.

Llámalo así -

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

Lo que necesita DjangoJSONEncodery listpara que su Queryseta json, ref: Python JSON serializar un objeto decimal

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


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

En pocas palabras list(yourQuerySet).

Miguel de Matos
fuente
2
Esto le da una lista de objetos, no una lista de dictados.
Flimm
0

Puede definir una función usando model_to_dict de la siguiente manera:

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
fuente