aero aero - 6 months ago 109
JSON Question

Correct way to use Django's ORM and Django Rest Framework to serialize a queryset of nested relationships?

What is the correct way to build a queryset that I can pass into a Django Rest Framework Serializer so as to get a data/json result of related nested objects.

For example, I have two models:

class Topping(models.Model):
name = models.CharField(max_length=50)

class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)


And my serializers:

class ToppingSerializer(serializers.Serializer):
name = serializers.CharField(required=True, max_length=50)

class PizzaSerializer(serializers.Serializer):
name = serializers.CharField(required=True, max_length=50)
toppings = ToppingSerializer(many=True, required=False)


How do I then create and pass in a query set to get the outcome of something like this:

[
{
"name": "Hawaiian",
"toppings": [
{"name": "Pinapple"},
{"name": "Canadian Bacon"},
{"name": "Cheese"}
]
},
{
"name": "Pepperoni Pizza",
"toppings": [
{"name": "Pepperoni"},
{"name": "Cheese"}
]
},
{
"name": "Jamaican",
"toppings": [
{"name": "Chicken"},
{"name": "Jerk"},
{"name": "Cheese"}
]
}
]





Please Note:



The Django Rest Framework has a good example in their documentation using ModelSerializer, but I will need this functionality without using ModelSerializer as my serialization needs will become quite customized beyond the DB model representations.




Additional Information:



The Django Rest Framework documentation for "Dealing with nested objects" is helpful, but I'm still not sure how to pass the correct queryset to such a "nested object serializer".

How can I create a "nested" queryset?

Answer

First of all you need to use ModelSerializer instead of Serializer, and provide fields meta attribute. If you are using default field configuration you don't need to provide serializer fields explicitly.

class ToppingSerializer(serializers. ModelSerializer):
    class Meta:
        model = Topping
        fields = ('name',)

class PizzaSerializer(serializers. ModelSerializer):
    class Meta:
        model = Pizza
        fields = ('name', 'toppings')

After that just use ListAPIView and provide your serializer to it.

class PizzaListApiView(ListAPIView):
    queryset = Pizza.objects.all()
    serializer_class = PizzaSerializer

Update

How can I create a "nested" queryset?

Nested means with ForeignKey or ManyToManyField in model, like your Pizza model. You could do prefetch_related on your queryset, for example if you want to do it explicitly(http://www.django-rest-framework.org/api-guide/serializers/#dealing-with-multiple-objects)

queryset = Pizza.objects.all().prefetch_related('toppings')
serializer = PizzaSerializer(queryset, many=True)
Comments