Django view to combine parent and child table data

Viewed 57

I've two Django models with a foreign key relationship:

class Parent(models.Model):
   id = models.IntegerField()
   parent_name = models.CharField()


class Child(models.Model)
   id = models.IntegerField()
   child_name = models.CharField()
   parent = models.ForeignKey(Parent, related_name='parent', on_delete=models.CASCADE)

Both tables are high volume so looking for something very efficient. What's the best way to write an efficient django view to return json as:

Expected JSON:

[
    {
        "id": 1,
        "parent_name": "Elon",
        "childs":
        [
           {
              "id": 101,
              "child_name": "Elon son"
          },

          {
              "id": 101,
              "child_name": "Elon daughter"
          }        
       ]
    },
  {
        "id": 2,
        "parent_name": "Jeff",
        "childs":
        [
           {
              "id": 101,
              "child_name": "Jeff son"
          },

          {
              "id": 101,
              "child_name": "Jeff daughter"
          }        
       ]
    }
]
1 Answers

The following view will return the JSON data generating only two database requests using prefetch_related() (using children as the related_name for Child.parent makes more sense, as Parent.children will then be the RelatedManager to access a parent's children - therefore I used it in this example).

from django.http import JsonResponse

def my_view(request):
    queryset = Parent.objects.all().prefetch_related("children")
    data = []
    for p in queryset:
        parent_data = {"id": p.pk, "parent_name": p.parent_name}
        parent_data["childs"] = [{"id": c.pk, "child_name": c.child_name} 
                                  for c in p.children.all()]
        data.append(parent_data)
    return JsonResponse(data)

You could also look into using QuerySet.values() if you want the queryset to immediately return a list of dictionaries, but if you need nested objects/dictionaries iterating over the queryset and constructing the list as in the example above is probably simpler.

Related