Richard
Richard

Reputation: 65600

Return QuerySet as JSON?

I'm working in Django 1.8 and having trouble finding the modern way to do this.

This is what I've got, based on Googling and this blog post:

results = PCT.objects.filter(code__startswith='a')
json_res = []
for result in results:
    json_res.append(result.as_dict())
return HttpResponse(json.dumps(json_res), content_type='application/json')

However this gives me 'PCT' object has no attribute 'as_dict'.

Surely there must be a neater way by now?

I was wondering if it was possible to use JSONResponse but frustratingly, the docs give no example of how to use JSONRespose with a queryset, which must be the most common use case. I have tried this:

results = PCT.objects.filter(code__startswith='a')
return JsonResponse(results, safe=False)

This gives [<PCT: PCT object>, <PCT: PCT object>] is not JSON serializable.

Upvotes: 10

Views: 37482

Answers (5)

djvg
djvg

Reputation: 14355

The accepted answer, using JsonResponse, is nice and simple. However, it does not return complete objects.

An alternative is to use Django's serializers. Here's an example copied verbatim from the admin actions documentation:

...
   response = HttpResponse(content_type="application/json")
   serializers.serialize("json", queryset, stream=response)
   return response

This is very similar to what happens in Django's JsonResponse, as can be seen in the source.

The main difference is that JsonResponse calls json.dumps() directly, and does not know how to handle querysets, whereas the example above uses serializers.serialize('json', ...), which does know how to handle querysets, and returns complete objects that can also be de-serialized later on.

If you want to save directly to file (using content-disposition: attachment to open a save dialog in the browser), you could use a FileResponse, for example:

...
    data = serializers.serialize('json', queryset)
    return FileResponse(
        io.BytesIO(data.encode('utf-8')),
        content_type='application/json',
        as_attachment=True,
        filename=f'{queryset.model.__name__.lower()}-objects.json'
    )

Upvotes: 0

devdrc
devdrc

Reputation: 2127

Most of these answers are out of date. Here's what I use:

views.py (returns HTML)

from django.shortcuts import render
from django.core import serializers

def your_view(request):
    data = serializers.serialize('json', YourModel.objects.all())
    context = {"data":data}
    return render(request, "your_view.html", context)

views.py (returns JSON)

from django.core import serializers
from django.http import HttpResponse

def your_view(request):
    data = serializers.serialize('json', YourModel.objects.all())
    return HttpResponse(data, content_type='application/json')

Upvotes: 4

Leistungsabfall
Leistungsabfall

Reputation: 6488

Simplest solution without any additional framework:

results = PCT.objects.filter(code__startswith='a').values('id', 'name')
return JsonResponse({'results': list(results)})

returns {'results': [{'id': 1, 'name': 'foo'}, ...]}

or if you only need the values:

results = PCT.objects.filter(code__startswith='a').values_list('id', 'name')
return JsonResponse({'results': list(results)})

returns {'results': [[1, 'foo'], ...]}

Upvotes: 32

wobbily_col
wobbily_col

Reputation: 11941

use values() to return a querydict, and pass that to json.dumps

values = PCT.objects.filter(code__startswith='a').values()
return HttpResponse(json.dumps(values), content_type='application/json')

https://docs.djangoproject.com/en/1.8/ref/models/querysets/#values

Upvotes: 5

Adrian Ghiuta
Adrian Ghiuta

Reputation: 1619

Take a look at Django's serialization framework. It allows not only the XML format, but also JSON and YAML.

Upvotes: 0

Related Questions