假设我有以下三种模型:
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
。
我的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
返回所有用户。没问题。
但是我正在寻找的功能是:
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 rest框架的新手。上面的类只是一个示例。忽略错误。
答案 0 :(得分:0)
在您的 viewset action
中将其他BusinessViewSet
添加为
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
答案 1 :(得分:0)
您应该使用django装饰器,它们分别是defineTabId()
和@list_route
作为视图集。但是请注意您的DRF版本。因为这些装饰器在DRF 3.8+中合并为@detail_route
。这是announcement。
@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)
在这里您可以从documentation中找到有关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/
的更多详细信息。
PS:不要忘记在代码中控制空实体结果。您应该使用正确的状态代码返回正确的响应。