简体   繁体   中英

Django Rest Framework: How to implement a nested logic?

Let's say I have three models as:

class User(AppModel):
    name = models.CharField(max_length=255)

class Business(AppModel):
    owner = models.ForeignKey("User", related_name="businesses", on_delete=models.CASCADE)
    legal_name = models.CharField(max_length=255)

class Invoice(AppModel):
    business = models.ForeignKey("Business", related_name="invoices", on_delete=models.CASCADE)
    amount = models.integerField()

As you can see, a user can have multiple businesses and a business can have multiple invoices .

My serializers.py:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields= ('name')

class BusinessSerializer(serializers.ModelSerializer):
    owner = UserSerializer(many=False)
    class Meta:
        model = Business
        fields= ('owner','legal_name')

class InvoiceSerializer(serializers.ModelSerializer):
    business= BusinessSerializer(many=False)
    class Meta:
        model = Invoice
        fields= ('business','amount')

views.py:

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

class BusinessViewSet(viewsets.ModelViewSet):
    queryset = Business.objects.all()
    serializer_class = BusinessSerializer

class InvoiceViewSet(viewsets.ModelViewSet):
    queryset = Invoice.objects.all()
    serializer_class = InvoiceSerializer

urls.py:

router = DefaultRouter()
router.register('user', UserViewSet, base_name='users')
router.register('business', BusinessViewSet, base_name='businesses')
router.register('invoice', InvoiceViewSet, base_name='invoices')
urlpatterns = router.urls

http://example.com/api/user returns all users. Not a problem.

But the functionality I'm looking for is:

  • http://example.com/api/business/ returns

    [ { "legal_name": "1business", "owner": 1, }, { "legal_name": "2business", "owner": 1, },]

  • http://example.com/api/business/1/ returns

    { "legal_name": "1business", "owner": 1, }

The above is ok. But I also need:

  • http://example.com/api/business/1/invoices/ should return

    [ { "business": 1, "amount": 100, }, { "business": 1, "amount": 999, },]

As well I should be able to create update delete those invoices there.

Any Help? I'm new to django rest framework. The above classes are just a sample. Ignore errors.

Add additional viewset action in your BusinessViewSet as

class BusinessViewSet(viewsets.ModelViewSet):
    queryset = Business.objects.all()
    serializer_class = BusinessSerializer

    

and change your urls.py as,

urlpatterns = [
                  

              ] + router.urls

You should use django decorators which are @list_route and @detail_route for your viewset. But be careful with your DRF version. Because those decorators merged together as @action in DRF 3.8+. Here is the announcement .

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status


class BusinessViewSet(viewsets.ModelViewSet):
    queryset = Business.objects.all()
    serializer_class = BusinessSerializer

    @action(detail=True, methods=["GET"], url_path="invoices")
    def invoices(self, request, pk=None):
        """
         Your codes comes here to return related result.
         pk variable contains the param value from url.
         if you do not specify the url_path properties then action will accept the function's name as url path.
        """
        entity = Invoice.objects.filter(business=pk)
        serializer = self.get_serializer(entity, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

Then, you will be able to call this endpoints from;

http://example.com/api/business/{{PK}}/invoices/
http://example.com/api/business/1/invoices/
http://example.com/api/business/3/invoices/
http://example.com/api/business/23/invoices/

Here you can find more details about @actions from documentation .

PS: Don't forget to control empty entity results in your codes. You should return correct response with correct status codes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM