#django #python

Today, I wanted to add a view which outputs the result of a Django queryset as a JSON array.

Sounds simple, but it took me a couple of minutes to figure out how to do it properly:

1from .models import *
2
3from django.http import JsonResponse
4
5def covid19_json(request):
6    data = CaseState.objects.values()
7    return JsonResponse(list(data), safe=False)

The things which are important:

  • You need to call .values() to get the actual queryset result
  • You then need to run it through list() to get it as a list
  • Lastly, you need to return a JsonResponse object with the parameter safe set to False to output it. The safe parameter is required as you're outputting a non-dictionary object.

If you want more control over how your models are converted to JSON, you can define for example a method called json on your model class:

 1from django.db import models
 2
 3class CaseState(models.Model):
 4    date                   = models.DateField(primary_key=True)
 5    country                = models.CharField(max_length=255)
 6    cases                  = models.IntegerField(blank=True, default=0)
 7    today_cases            = models.IntegerField(blank=True, default=0)
 8    deaths                 = models.IntegerField(blank=True, default=0)
 9    today_deaths           = models.IntegerField(blank=True, default=0)
10    recovered              = models.IntegerField(blank=True, default=0)
11    active                 = models.IntegerField(blank=True, default=0)
12    critical               = models.IntegerField(blank=True, default=0)
13    cases_per_one_million  = models.IntegerField(blank=True, default=0)
14    deaths_per_one_million = models.IntegerField(blank=True, default=0)
15
16    def json(self):
17        return {
18            'date':    str(self.date),
19            'country': self.country,
20            'cases':   self.cases,
21        }

Then, do the following in the view function:

1import json
2
3from .models import *
4
5from django.http import HttpResponse
6
7def covid19_json(request):
8    data = [i.json() for i in CaseState.objects.all()]
9    return HttpResponse(json.dumps(data), content_type="application/json")

The second approach doesn't require a one on one match between the model and the json output.