django-restframework之视图组件及规范化接口

django-restframework之视图组件及规范化节后

一 前言

在写接口的时候,比如增删查改,在获取所有的数据以及获取单个数据时,具体的代码逻辑几乎完全一样,就是参数不同,所以可以通过视图类来减少代码冗余。

二 规范化接口

在之前的代码都是做 if 判断来进行代码执行的逻辑,而强壮的代码必然会有 try-except 用来捕捉程序的不确定错误,这样可以减少代码的错误发生概率。

三 原始版本接口

class Book(APIView):
    authentication_classes = [authticate_classes.BookAuth]
    permission_classes = [permiss_classes.LoginPermission]
    # throttle_classes = [thrott_classes.BookThrottle]
    throttle_classes = []
    # authentication_classes = []

    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, id):
        print(request.user, '444')
        response = {'status': 100, 'msg': None}
        book_obj = models.Book.objects.filter(pk=id).first()
        if book_obj:
            book_ser = myser.BookSer(book_obj, many=False)
            response['book'] = book_ser.data
        else:
            response['msg'] = '图书没有对象'
            response['status'] = 101
        return Response(response)

    def put(self, request, id):
        response = {'status': 100, 'msg': None}
        book_obj = models.Book.objects.filter(pk=id).first()
        book_ser = myser.BookSer(data=request.data, instance=book_obj)
        # 新方法,使用序列化组件保存,但是必须是继承自 ModelSerializer 的序列化类,这样才可以知道要保存的表模型
        if book_ser.is_valid():
            # save既可以修改也可以新增
            book_ser.save()
            response['book'] = book_ser.data
        else:
            response['msg'] = book_ser.errors
        return Response(response)

    def delete(self, request, id):
        response = {'status': 100, 'msg': None}
        models.Book.objects.filter(pk=id).delete()
        response['msg'] = '删除成功'
        return Response(response)

四 规范化接口

class Book(APIView):
    def get(self, request, id):
        response = MyResponse()
        try:
            book = models.Book.objects.get(pk=id)
            book_ser = BookSerializer(instance=book, many=False)
            response.book = book_ser.data
        except ObjectDoesNotExist as  e:
            response.status = 101
            response.msg = 'id不存在'

        except Exception as e:
            print(e)
            response.status = 201
            # response.msg = '您的操作有误'
            response.msg = str(e)
        return Response(response.get_dic)

    def put(self, request, id):
        response = MyResponse()
        try:
            book = models.Book.objects.get(pk=id)
            book_ser = BookSerializer(data=request.data, instance=book)
            if not book_ser.is_valid():
                raise Exception('数据校验失败')
            book_ser.save()
            response.book = book_ser.data
            response.msg = '修改成功'
        except ObjectDoesNotExist as  e:
            response.status = 101
            response.msg = 'id不存在'

        except Exception as e:
            print(e)
            response.status = 201
            # response.msg = '您的操作有误'
            response.msg = str(e)
        return Response(response.get_dic)

    def delete(self, request, id):
        response = MyResponse()
        try:
            models.Book.objects.filter(pk=id).delete()
            response.msg = '删除成功'
        except Exception as e:
            print(e)
            response.status = 201
            # response.msg = '您的操作有误'
            response.msg = str(e)
        return Response(response.get_dic)

五 视图类相关使用

原理就是 restframework 框架帮我们封装了一些方法,我们只要修改某些配置就可以使用它提供的方法,可以大大的减少代码的冗余。

封装类里面需要使用的方法:

  • DestroyModelMixin:删除
  • UpdateModelMixin,:更新
  • RetrieveModelMixin :获取一条
  • CreateModelMixin:新增一条
  • ListModelMixin:获取所有

这几个方法和增删查改的接口的作用是一样的,所以只需要把相关的 model 对象和序列化类传过去就可以无缝衔接。

1. 使用 mixin 类和 generice 类编写视图

from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin
from rest_framework.generics import GenericAPIView
class PublishView(ListModelMixin,CreateModelMixin,GenericAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

class PublishDetailView(RetrieveModelMixin,UpdateModelMixin,
                        DestroyModelMixin,GenericAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers
    def get(self,request,*args,**kwargs):
        return self.retrieve(request,*args,**kwargs)
    def put(self,request,*args,**kwargs):
        return self.update(request,*args,**kwargs)
    def delete(self,request,*args,**kwargs):
        return self.destroy(request,*args,**kwargs)

2. 使用 generics 下的 ListCreateAPIView,RetrieveUpdateDestroyAPIView

from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
class PublishView(ListCreateAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

class PublishDetailView(RetrieveUpdateDestroyAPIView):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

3. 使用 ModelViewSet

路由:

url(r'^publish/$', views.PublishView.as_view({'get':'list','post':'create'})),
    url(r'^publish/(?P<pk>\d+)/$', views.PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),

视图:

from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

最后只封装成一个视图类就可以实现两套路由,具体逻辑就是as_view后面的参数的映射关系,最后可以根据 mro 列表来查找对应的执行方法。

六 ModelViewSet 的执行流程

1. class ModelViewSet

2. class GenericViewSet

3. ViewSetMixin中的 as_view

posted @ 2019-02-27 09:01  rsuxwvilc  阅读(179)  评论(0编辑  收藏  举报