-
Notifications
You must be signed in to change notification settings - Fork 10
DRF Extra Actions
以bills
账目资源为例,我们需要一个批量删除接口,但DRF
视图集中并未包含,这需要我们自定义一个额外接口;
文章marking-extra-actions-for-routing
有介绍自定义接口的实现方式;
这里提及schema
的原因在于,采用@action
装饰器实现的接口,其在swagger
文档中展示的请求参数是采用了serializer_class
中设置的字段参数,而当我在实现一个批量删除功能的接口时,这些参数完全用不上,需要定义自己的请求参数;
那么如何自定义接口参数于swagger文档中呢?
这里在文档per-view-schema-customisation
中提及了get_link(self, path, method, base_url)
这个方法,它可以为视图接口指定请求参数;
# apps/bills/schemas.py
from rest_framework.schemas import AutoSchema
from coreapi import Field, Link, document
import coreschema
class BillSchema(AutoSchema):
def get_link(self, path, method, base_url):
link = super().get_link(path, method, base_url)
# 无法指定bill_ids数组中的元素类型,这里元素定义为int但实际为str,无法处理...
batch_del_fields = [
Field(
'bill_ids',
location='form',
required=True,
schema=coreschema.Array(items=coreschema.Integer(),unique_items=True)
)
]
fields = link.fields
if link.url == '/api/v1/bills/batch_del/':
fields = tuple(batch_del_fields)
link = Link(url=link.url, action=link.action, encoding=link.encoding, fields=fields, description=link.description)
document.Link()
return link
这里我们为Bills
定义了一个schema
,重写了get_link()
该方法,方法内我们定义了一个名为bill_ids
的数组类型请求参数,且规定在URL为:/api/v1/bills/batch_del/
的时候设置为该自定义参数;
注:这里有个坑,schema=coreschema.Array(items=coreschema.Integer(),unique_items=True)
这段定义的是一个内部元素为整形的数组,但实际在swagger
中数组内部是str
类型,暂无法解决,但没有太大影响;
然后,还需要再视图中指定schema
:
# apps/bills/views.py
from apps.bills.schemas import BillSchema
...
class BillsViewSet(viewsets.ModelViewSet):
serializer_class = BillSerializer
...
schema = BillSchema() # 设置schema
...
schema
处理完后,我们只是能处理了swagger
文档的展示,而接口本身需要的请求入参验证,还需要自定义一个序列化器支持;
class BatchDelSerializer(serializers.Serializer):
bill_ids = serializers.ListField(required=True, child=serializers.IntegerField())
我们定义了参数bill_ids
,它是一个成员为整形的列表;
最后我们回到视图,实现批量删除接口:
# apps/bills/views.py
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from apps.bills.schemas import BillSchema
from apps.bills.serializers import BillSerializer, BatchDelSerializer
...
class BillsViewSet(viewsets.ModelViewSet):
serializer_class = BillSerializer
...
schema = BillSchema()
...
# 批量删除
@action(methods=['delete'], detail=False)
def batch_del(self, request):
"""
batch delete bills
"""
serializer = BatchDelSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
bill_ids = serializer.data.get('bill_ids')
bills_data = Bills.objects.filter(pk__in=bill_ids)
bills_data.delete()
return Response(status.HTTP_204_NO_CONTENT)
... 累到整夜不能睡,夜色哪裡都是美 ...
昨日擔當 昨日敢想
昨日轉眼 就跌撞
夏時夢長 秋時晝短
清冽途上 不遠望