繁体   English   中英

Django Rest Framework:如何实现嵌套逻辑?

[英]Django Rest Framework: How to implement a nested logic?

假设我有三个模型:

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()

如您所见,一个user可以有多个businesses ,一个business可以有多个invoices

我的序列化程序.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')

视图.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

网址.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返回所有用户。 不是问题。

但我正在寻找的功能是:

  • http://example.com/api/business/返回

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

  • http://example.com/api/business/1/返回

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

以上是可以的。 但我还需要:

  • http://example.com/api/business/1/invoices/应该返回

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

同样,我应该能够在那里创建更新删除那些发票。

任何帮助? 我是 Django 休息框架的新手。 上面的类只是一个示例。 忽略错误。

在您的BusinessViewSet添加其他viewset action

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

    def get_invoice(self, request, *args, **kwargs): invoice_queryset = self.get_object().invoices.all() serializer = InvoiceSerializer(invoice_queryset, many=True) return Response(serializer.data)

并将您的urls.py更改为

urlpatterns = [
                  url(r'business/(?P<pk>\d+)/invoice/', BusinessViewSet.as_view({"get": "get_invoice"})),

              ] + router.urls

你应该使用Django装饰这是@list_route@detail_route您的视图集中。 但是请注意您的DRF版本。 因为这些装饰器在DRF 3.8+中作为@action合并在一起。 这是公告

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)

然后,您将可以从以下位置调用此端点:

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/

在这里,您可以从文档中找到有关@actions更多详细信息。

PS:不要忘记在代码中控制空实体结果。 您应该使用正确的状态代码返回正确的响应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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