Como faço para converter um Django QuerySet em uma lista de dicts?

122

Como posso converter um Django QuerySet em uma lista de dicts? Não encontrei uma resposta para isso, então estou me perguntando se estou perdendo algum tipo de função auxiliar comum que todos usam.

Mridang Agarwalla
fonte

Respostas:

176

Use o .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: o resultado é um QuerySetque geralmente se comporta como uma lista, mas não é realmente uma instância de list. Use list(Blog.objects.values(…))se você realmente precisar de uma instância de list.

David Wolever
fonte
7
sim, você especifica quais campos deseja values()retornar, passando-os como argumentos. Também tenha cuidado, embora pareça que os valores retornam uma lista de dados, na verdade, é um <class 'django.db.models.query.ValuesQuerySet'>e não uma lista.
dm03514
10
na verdade, isso não retorna uma lista
astreltsov
Além disso, você não pode obter os resultados dos métodos de instância do seu objeto com values(), não sei se existe um bom método para fazer o mesmo, values()mas também com a chamada dos métodos de instância ?!
Asara
34

O .values()método retornará um resultado do tipo ValuesQuerySetque normalmente é o que você precisa na maioria dos casos.

Mas, se desejar, você pode transformar ValuesQuerySetem uma lista Python nativa usando a compreensão de lista Python, conforme ilustrado no exemplo abaixo.

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

Acho que o acima ajuda se você estiver escrevendo testes de unidade e precisar afirmar que o valor de retorno esperado de uma função corresponde ao valor de retorno real, caso em que ambos expected_resulte actual_resultdevem ser do mesmo tipo (por exemplo, dicionário).

actual_result = some_function()
expected_result = {
    # dictionary content here ...
}
assert expected_result == actual_result
Arthur Rimbun
fonte
17
Ou você pode simplificar a conversão para lista com estelist(result)
Adiyat Mubarak
12

Se você precisar de tipos de dados nativos por algum motivo (por exemplo, serialização JSON), esta é minha maneira rápida e suja de fazer isso:

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

Como você pode ver, construir o dict dentro da lista não é realmente SECO, então se alguém conhece uma maneira melhor ...

Semmel
fonte
Parece que tenho feito funcionar com data = list( blogs )e então json.dumps( data ). Um array sai com um monte de objetos do lado do javascript, nenhuma análise necessária.
Arthur Tarasov
3

Você não define exatamente a aparência dos dicionários, mas provavelmente está se referindo a QuerySet.values(). Da documentação oficial do Django :

Retorna a ValuesQuerySet- uma QuerySetsubclasse que retorna dicionários quando usado como iterável, em vez de objetos de instância de modelo.

Cada um desses dicionários representa um objeto, com as chaves correspondentes aos nomes dos atributos dos objetos do modelo.

Bernhard Vallant
fonte
2

Digite o elenco para a lista

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

    json.dumps(list(job_reports))
Saurabh Chandra Patel
fonte
1

Você pode usar o values()método no dict obtido no campo do modelo do Django no qual faz as consultas e, então, pode acessar facilmente cada campo por um valor de índice.

Chame assim -

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

Você precisa DjangoJSONEncodere listfazer o seu Querysetpara json, ref: Python JSON serializar um objeto Decimal

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


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

Basta colocar list(yourQuerySet).

Miguel de Matos
fonte
2
Isso dá a você uma lista de objetos, não uma lista de dictos.
Flimm
0

Você pode definir uma função usando model_to_dict da seguinte maneira:

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
fonte