TomR
TomR

Reputation: 3056

How to access full object JSON graph from Django REST?

I have Django models, serializers and views:

from django.db import models

# Create your models here.
class Contract(models.Model):
    contract_no = models.IntegerField(blank=False, unique=True)
    customer = models.IntegerField(blank=False)
    agent = models.IntegerField(blank=False)
    agency = models.IntegerField(blank=False)
    cont_date = models.DateField()

    def __str__(self):
        """Return a human readable representation of the model instance."""
        return "{}".format(self.contract_no)

class ContractOrder(models.Model):
    order_no = models.IntegerField(blank=False, unique=True)
    order_date = models.DateField()
    contract = models.ForeignKey(Contract, on_delete=models.DO_NOTHING)

    def __str__(self):
        return self.order_no

    class Meta:
        ordering = ('order_no',)


from rest_framework import serializers
from .models import Contract
from .models import ContractOrder

class ContractSerializer(serializers.ModelSerializer):
    """Serializer to map the Model instance into JSON format."""

    class Meta:
        """Meta class to map serializer's fields with the model fields."""
        model = Contract
        fields = ('contract_no', 'customer', 'agent', 'agency', 'cont_date')
        #read_only_fields = ('date_created', 'date_modified')

class ContractOrderSerializer(serializers.ModelSerializer):
    """Serializer to map the Model instance into JSON format."""

    class Meta:
        """Meta class to map serializer's fields with the model fields."""
        model = ContractOrder
        fields = ('order_no', 'order_date', 'contract')
        #read_only_fields = ('date_created', 'date_modified')


from rest_framework import generics
from .serializers import ContractSerializer
from .models import Contract
from .serializers import ContractOrderSerializer
from .models import ContractOrder

class ContractCreateView(generics.ListCreateAPIView):
    """This class defines the create behavior of our rest api."""
    queryset = Contract.objects.all()
    serializer_class = ContractSerializer

    def perform_create(self, serializer):
        """Save the post data when creating a new bucketlist."""
        serializer.save()

class ContractOrderCreateView(generics.ListCreateAPIView):
    """This class defines the create behavior of our rest api."""
    queryset = ContractOrder.objects.all()
    serializer_class = ContractOrderSerializer

    def perform_create(self, serializer):
        """Save the post data when creating a new bucketlist."""
        serializer.save()

And the results /contracts and /contract_orders JSON messages are simple:

[{"contract_no":1,"customer":1,"agent":1,"agency":1,"cont_date":"2018-04-26"},{"contract_no":2,"customer":2,"agent":2,"agency":2,"cont_date":"2018-04-25"}]

[{"order_no":1,"order_date":"2018-04-26","contract":1}]

But I wish to have more expanded JSON messages, specifically:

  1. Contract JSON entity should have array of ContractOrder entities (in my case contract 1 should have array with 1 entry)

  2. ContractOrder JSON entity should have expanded contract entity - at present contract field (in JSON) contains only scalar value 1, but I would like to have full Contract entity.

Of course - there will be situations when the JSON graph should be expanded fully, when it should be contracted and then there will be situations when the expansion should be partial? Is it possible to achieve this in Django?

I have experience that in Java JPA/Hibernate/Spring it is possible to control the entity graph (in memory) and JSON view of the entity graph (in REST) using annotations @OneToMany and @JsonView (from com.fasterxml.jackson.annotation.JsonView library) but how to achieve this in Django - both - in memory and in REST JSON messages?

Upvotes: 1

Views: 324

Answers (1)

rtindru
rtindru

Reputation: 5347

Change your serializers as follows:

class SimpleContractOrderSerializer(serializers.ModelSerialiser):  # Required; otherwise you get into a recursive loop.
    class Meta:
        """Meta class to map serializer's fields with the model fields."""
        model = ContractOrder
        fields = ('order_no', 'order_date',)

class ContractSerializer(serializers.ModelSerializer):
    """Serializer to map the Model instance into JSON format."""
    contract_order = SimpleContractOrderSerializer(source='contractorder', many=True, read_only=True)

    class Meta:
        """Meta class to map serializer's fields with the model fields."""
        model = Contract
        fields = ('contract_no', 'customer', 'agent', 'agency', 'cont_date')
        #read_only_fields = ('date_created', 'date_modified')

class ContractOrderSerializer(serializers.ModelSerializer):
    """Serializer to map the Model instance into JSON format."""
    contract = ContractSerializer(read_only=True)

    class Meta:
        """Meta class to map serializer's fields with the model fields."""
        model = ContractOrder
        fields = ('order_no', 'order_date', 'contract')
        #read_only_fields = ('date_created', 'date_modified')

Read more here: http://www.django-rest-framework.org/api-guide/relations/#nested-relationships

Upvotes: 3

Related Questions