How to return a query in JSON format with extra values and custom Keys?

Asked

Viewed 1,166 times

2

I want to return the result in JSON following this format:

{"cadastros": [
    {"id": 1, "STATUS": true, "pessoas": [], "podeEscrever": true},
    {"id": 2, "STATUS": false, "pessoas": ['Maria', 'Ana'], "podeEscrever": true},
], 'principal': true}

py.models:

class MyModel(models.Model):
    status = models.BooleanField()
    pessoas = models.ManyToManyField(Pessoa, blank=True)
    podeescrever = models.BooleanField()

See that in format JSON exists podeEscrever uppercase letter, so the result should follow this format as well.

The main idea is to use the library simplejson to manipulate the result and return the JSON in the desired format.

py views.:

def minha_views(request):
    p = Pessoa.objects.values()
    data = simplejson.dumps(p)
    # aqui seria formatado
    return HttpResponse(data, content_type='application/json; charset=utf8')

My difficulty is in formatting the JSON, i can return the results of the query directly to JSON, but I don’t know how to manipulate to add new keys and change the field name podeescrever for podeEscrever.

Another thing that’s happening is that the field pessoas that is ManytoManyField does not return in the JSON if empty, the correct one was to return with an empty list [] if there are no items.

It does not seem to be difficult to perform this procedure, someone knows how to solve this problem?

2 answers

3


I would use list understandings in both cases:

return HttpResponse(json.dumps({
    "principal": True,
    "cadastros":[{
        "id":p.id,
        "STATUS":p.status,
        "podeEscrever":p.podeescrever,
        "pessoas":[unicode(pessoa) for pessoa in p.pessoas.all()],
    } for p in MyModel.objects.all().prefetch_related("pessoas")],
}), content_type='application/json; charset=utf8')

This solution can be a bit laborious if the models are large, but it has the advantage of allowing both customizing the names of the attributes, which appear and which do not, and also their format (it is very common for me to have to format dates, for example, in a non-standard way when generating JSON).

Notes: 1) I usually use json and not simplejson, I don’t know if it makes a difference; 2) Notice the use of prefetch_related to reduce the number of queries to the minimum necessary.

  • In this case the real model is great, but doing it this way seems more efficient. I installed the new version of simplejson because I was having a problem with decimal, I just can’t remember now if it was with the json or with simplejson of the project. In relation to the prefetch_related I have not yet understood how it works, whenever you consult a field ManyToMany (p.pessoas.all()) should I wear prefetch_related to improve performance?

  • 1

    @Orion It’s not just one ManyToMany, but with any field that makes a Join between tables (ex.: ForeignKey). Let’s say the model A have a field b referencing a model B. Let’s also say that A has 1000 lines, each referencing a separate line of B (also 1000). If you do for a in A.objects.all(): print (a.b) Django’s gonna do it 1001 BD! But with for a in A.objects.all().prefetch_related("b"): print (a.b) he’ll just do 2. I’m not sure the same goes for the call from values, but I think so (I would have to test).

2

I was able to solve it this way:

pessoas = Pessoa.objects.values()
pessoas_modificado = []

for p in pessoas:

    # altera o nome das chaves:
    p['STATUS'] = p.pop('status')
    p['podeEscrever'] = p.pop('podeescrever')

    # retorna lista vazia caso não exista pessoas
    p['pessoas'] = p.get('pessoas', [])

    # adiciona o dicionario a nova lista:
    pessoas_modificado.append(p)

# cria a formatação esperada
dicionario = {'cadastros': list(pessoas_modificado), 'principal': True}

# retorna em JSON
return HttpResponse(simplejson.dumps(dicionario), content_type='application/json; charset=utf8')

Browser other questions tagged

You are not signed in. Login or sign up in order to post.