django rest framework的ModelViewSet非常爽,省了一大堆业务逻辑代码,跟自己手写restful的API 比至少减了100多行代码,而且serializer这种东西都是复制就行,少耗费好多脑细泡。create和update的时候的各种异常根本不用自己检查,直接就能报出来,加上django的国际化功能,直接甩中文,贼轻松,类似这样:
{
"name": [
"具有 人物名称 的 人物 已存在。"
],
"category": [
"列表不能为空。"
]
}
配合rest framework的Response和status,根据http状态码判断返回状态然后直接读取数据体,非常方便。不过和前端配合的话,需要返回code和msg,所以要自定义一下返回内容。根据serializer.errors的情况就可以判断返回是否异常,这样可以从return Response
的地方做个修改就可以把所有返回内容都加上code和msg了,不用每个return
都写。
如果serializer.errors有值,就是报错了,就返回
{'code': 0, 'msg': '失败', 'data': serializer.errors}
如果没报错,就返回
{'code': 1, 'msg': '成功', 'data': serializer.data}
既然所有Response都要调整,最好当然直接改Response,一看源码,还防着我这手儿,不让传serializer,只让传serializer.data:
if isinstance(data, Serializer):
msg = (
'You passed a Serializer instance as data, but '
'probably meant to pass serialized `.data` or '
'`.error`. representation.'
)
raise AssertionError(msg)
虽然仍然可以改,不过这个Response的位置太根部了,除非改源码,否则改了Response,所有return Response
的地方都要改。那就换个思路,改ModelViewSet吧。
ModelViewSet直接继承了6个父类:
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass
只要调整那几个混入类里面的对应的方法的return Response
就可以了。以update为例:
class MyModelViewSet(viewsets.ModelViewSet):
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
is_valid = serializer.is_valid(raise_exception=False)
#######
if not is_valid:
return Response({'code': 0, 'msg': '失败', 'data': serializer.errors})
self.perform_update(serializer)
######
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response({'code': 1, 'msg': '成功', 'data': serializer.data})
注意is_valid = serializer.is_valid(raise_exception=False)
源码是raise_exception=True
,要改成False,不然就抛出异常在serializer里处理,不走下面的代码了。
然后只要在继承ModelViewSet
的地方改为继承MyModelViewSet
就ok了。