zoukankan      html  css  js  c++  java
  • DAY101

    一、视图组件

    1.基本视图

    class Books(APIView):
        def get(self, request, *args, **kwargs):
            books = models.Book.objects.all()
            response = {'status': 200, 'msg': '查询成功', 'data': None}
            ret = BooksSerializer(books, many=True)
            response['data'] = ret.data
            return JsonResponse(response, safe=False)
    
        def post(self, request, *args, **kwargs):
            response = {'status': 200, 'msg': '创建成功', 'data': None, 'error': None}
            ret = BooksSerializer(data=request.data)
            if ret.is_valid():
                ret.save()
                response['data'] = ret.data
            else:
                response['error'] = ret.errors
            return JsonResponse(ret.data, safe=False)
    
    
    class BooksDetail(APIView):
        def get(self, request, id, *args, **kwargs):
            books = models.Book.objects.filter(pk=id).first()
            response = {'status': 200, 'msg': '查询成功', 'data': None}
            if books:
                ret = BooksSerializer(books, many=False)
                response['data'] = ret.data
            else:
                response['msg'] = '查无此信息'
            return JsonResponse(response, safe=False)
    
        def put(self, request, id, *args, **kwargs):
            books = models.Book.objects.filter(pk=id).first()
            response = {'status': 200, 'msg': '更新成功', 'data': None, 'error': None}
            ret = BooksSerializer(data=request.data, instance=books)
            if ret.is_valid():
                ret.save()
                response['data'] = ret.data
            else:
                response['error'] = ret.errors
            return JsonResponse(ret.data, safe=False)
    
        def delete(self, request, id, *args, **kwargs):
            books = models.Book.objects.filter(pk=id).first()
            response = {'status': 200, 'msg': '删除成功', 'data': None}
            ret = BooksSerializer(books, many=False)
            response['data'] = ret.data
            books.delete()
            return JsonResponse(response, safe=False)
    

    2.利用mixin类简化视图

    基本视图中的有些代码可以进一步简化,比如说表名和序列化对象可以用一个

    from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin,DestroyModelMixin
    from rest_framework.generics import GenericAPIView
    
    
    class Books(GenericAPIView, ListModelMixin, CreateModelMixin):
        # queryset和serializer_class是GenericAPIView定义必须要写的
        queryset = models.Book.objects.all()
        serializer_class = BooksSerializer
    
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
    
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)
    
    
    class BooksDetail(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
        queryset = models.Book.objects.all()
        serializer_class = BooksSerializer
    	# 必须传pk,因为这是RetrieveModelMixin等调用的GenericAPIView方法规定的
        def get(self, request, pk):
            return self.retrieve(request, pk)
    
        def put(self, request, pk):
            return self.update(request, pk)
    
        def delete(self, request, pk):
            return self.destroy(request, pk)
    

    2.1 mixin类源码分析

    # ListModelMixin
    # 以ListModelMixin举例,它实际上是,把我们写的基本视图中的代码进行了封装,而对于用户只要继承该类,并且引用就行了
    class ListModelMixin(object):
        """
        List a queryset.
        """
        def list(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    

    2.2 GenericAPIView源码分析

    # GenericAPIView
    # mixin类中的一些方法是调用GenericAPIView中的方法,所以视图类如果继承mixin类,就必须也继承GenericAPIView
    # 由于GenericAPIView已经继承了APIView,所以视图不必再继承APIView了
    class GenericAPIView(views.APIView):
        queryset = None
        serializer_class = None
    
        lookup_field = 'pk'
        lookup_url_kwarg = None
    
        filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
    
        pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
    
        # get_queryset:获得视图类里的queryset表格的所有数据
        def get_queryset(self):
            queryset = self.queryset
            # 判断queryset是否是QuerySet实例化后的对象
            if isinstance(queryset, QuerySet):
                # 如果是QuerySet对象,就再次all()
                queryset = queryset.all()
            return queryset
    	
        # get_object:获得单条数据
        def get_object(self):
            # 对所及数据进行过滤
            queryset = self.filter_queryset(self.get_queryset())
    		
            ........
            
            filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
            obj = get_object_or_404(queryset, **filter_kwargs)
    
            self.check_object_permissions(self.request, obj)
    
            return obj
    	
        # get_serializer:返回序列化对象
        def get_serializer(self, *args, **kwargs):
            serializer_class = self.get_serializer_class()
            kwargs['context'] = self.get_serializer_context()
            return serializer_class(*args, **kwargs)
    
        # get_serializer_class:获得视图里的序列化对象
        def get_serializer_class(self):
    		
            ........
    
            return self.serializer_class
    
        def get_serializer_context(self):
    		........
    
        def filter_queryset(self, queryset):
    		........
    
        @property
        def paginator(self):
    		........
    
        def paginate_queryset(self, queryset):
    		........
    
        def get_paginated_response(self, data):
    		........
    

    3.利用generice类简化代码

    虽然已经简化了代码,但是get和post等方法的代码还是重复了,都是一条代码,还可以再一步简略

    from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
    
    
    class Books(ListCreateAPIView):
        queryset = models.Book.objects.all()
        serializer_class = BooksSerializer
    
    
    class BooksDetail(RetrieveUpdateDestroyAPIView):
        queryset = models.Book.objects.all()
        serializer_class = BooksSerializer
    

    3.1 ListCreateAPIView源码分析

    # ListCreateAPIView:其实是对mixins类的进一步封装,这样视图里就不需用写get和post了,只要继承ListCreateAPIView就可以,RetrieveUpdateDestroyAPIView也是一样的
    class ListCreateAPIView(mixins.ListModelMixin,
                            mixins.CreateModelMixin,
                            GenericAPIView):
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
    
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs)
    

    4.使用ModelViewSet

    进一步简化代码后,我们发现,两个视图的代码变得一样了,那么可不可以更进一步封装,drf提供了一个方法可以把两个视图合并。

    url(r'^books/',views.Books.as_view({'get':'list','post':'create'})),
    url(r'^booksdetail/(?P<pk>d+)', views.Books.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
    
    from rest_framework.viewsets import ModelViewSet
    
    class Books(ModelViewSet):
        queryset = models.Book.objects.all()
        serialzizer_class = BooksSerializer
    

    4.1ModelViewSet源码分析

    # 第一步
    # ModelViewSet
    # 其实是对所有的mixins类继承
    # GenericViewSet才是关键
    class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):
        pass
    
    
    # 第二步
    # GenericViewSet
    # 是对ViewSetMixin和GenericAPIView的继承
    # 由于继承了GenericAPIView,而GenericAPIView已经继承了APIView,所以视图不必再继承APIView
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
        pass
    
    # 第三步
    # ViewSetMixin
    # ViewSetMixin是对as_view的重写
    class ViewSetMixin(object):
       @classonlymethod
        def as_view(cls, actions=None, **initkwargs):
            # actions={'get':'retrieve','put':'update','delete':'destroy'}
            # 是路由层传来的参数
            cls.name = None
            cls.description = None
            cls.suffix = None
            cls.detail = None
            cls.basename = None
            
            .......
        	
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
    
                self.action_map = actions
    			# 对action循环
                # 请求方式:method='get'  对应方法:action='list'
                for method, action in actions.items():
                    # 把action的,也就是list的内存地址赋给了handler
                    handler = getattr(self, action)
                    # 把handler的,也就是list的内存地址赋给了method
                    # 也就是说,执行get方法就是执行list方法
                    setattr(self, method, handler)
    
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get
    
                self.request = request
                self.args = args
                self.kwargs = kwargs
    
                return self.dispatch(request, *args, **kwargs)
    
            update_wrapper(view, cls, updated=())
    
            update_wrapper(view, cls.dispatch, assigned=())
    
            view.cls = cls
            view.initkwargs = initkwargs
            view.actions = actions
            return csrf_exempt(view)
    

    二、路由控制

    1.自定义路由

    url(r'^books/', views.Books.as_view()),
    url(r'^booksdetail/(?P<pk>d+)', views.BooksDetail.as_view()),
    
    class Books(APIView):
        def get(self, request, *args, **kwargs):
            books = models.Book.objects.all()
            response = {'status': 200, 'msg': '查询成功', 'data': None}
            ret = BooksSerializer(books, many=True)
            response['data'] = ret.data
            return JsonResponse(response, safe=False)
    
        def post(self, request, *args, **kwargs):
            response = {'status': 200, 'msg': '创建成功', 'data': None, 'error': None}
            ret = BooksSerializer(data=request.data)
            if ret.is_valid():
                ret.save()
                response['data'] = ret.data
            else:
                response['error'] = ret.errors
            return JsonResponse(ret.data, safe=False)
    
    
    class BooksDetail(APIView):
        def get(self, request, id, *args, **kwargs):
            books = models.Book.objects.filter(pk=id).first()
            response = {'status': 200, 'msg': '查询成功', 'data': None}
            if books:
                ret = BooksSerializer(books, many=False)
                response['data'] = ret.data
            else:
                response['msg'] = '查无此信息'
            return JsonResponse(response, safe=False)
    
        def put(self, request, id, *args, **kwargs):
            books = models.Book.objects.filter(pk=id).first()
            response = {'status': 200, 'msg': '更新成功', 'data': None, 'error': None}
            ret = BooksSerializer(data=request.data, instance=books)
            if ret.is_valid():
                ret.save()
                response['data'] = ret.data
            else:
                response['error'] = ret.errors
            return JsonResponse(ret.data, safe=False)
    
        def delete(self, request, id, *args, **kwargs):
            books = models.Book.objects.filter(pk=id).first()
            response = {'status': 200, 'msg': '删除成功', 'data': None}
            ret = BooksSerializer(books, many=False)
            response['data'] = ret.data
            books.delete()
            return JsonResponse(response, safe=False)
    

    2.半自动路由(需继承ModelViewSet)

    url(r'^books/',views.Books.as_view({'get':'list','post':'create'})),
    url(r'^booksdetail/(?P<pk>d+)', views.Books.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
    
    from rest_framework.viewsets import ModelViewSet
    
    class Books(ModelViewSet):
        queryset = models.Book.objects.all()
        serialzizer_class = BooksSerializer
    

    3.全自动路由

    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    from rest_framework import routers
    # 生成一个router对象
    router = routers.DefaultRouter()
    # 需要传两个参数,第一个参数就是匹配的路径,第二个参数,是视图类
    router.register('books',views.Books)
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        # 不用匹配正则,空字符串就行
        url('',include(router.urls))
    ]
    
    # url('',include(router.urls))会自动创建以下6个URL
    # '^books/$ [name='book-list']'
    # '^books.(?P<format>[a-z0-9]+)/?$ [name='book-list']'
    # '^books/(?P<pk>[^/.]+)/$ [name='book-detail']'
    # '^books/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)/?$ [name='book-detail']'
    # '^$ [name='api-root']'
    # '^.(?P<format>[a-z0-9]+)/?$ [name='api-root']'
    
    from rest_framework.viewsets import ModelViewSet
    
    # 视图一定要是继承ModelViewSet的
    class Books(ModelViewSet):
        queryset = models.Book.objects.all()
        serializer_class = BooksSerializer
    
    

    三、响应器

    1.基本使用

    from rest_framework.renderers import  HTMLFormRenderer,BrowsableAPIRenderer,AdminRenderer,JSONRenderer
    
    class Books(APIView):
        # 局部指定使用
        renderer_classes = [AdminRenderer,]
        
    # setting.py
    # 全局使用
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer']
    }
    
    根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。
    用户请求URL:
        http://127.0.0.1:8000/test/?format=json
        http://127.0.0.1:8000/test.json
                
    显示json格式:JSONRenderer
    
    访问URL:
    
    	http://127.0.0.1:8000/test/?format=json
    	http://127.0.0.1:8000/test.json
    	http://127.0.0.1:8000/test/
     
    默认显示格式:BrowsableAPIRenderer(可以修改它的html文件)
    
    访问URL:
    
    	http://127.0.0.1:8000/test/?format=api
    	http://127.0.0.1:8000/test.api
    	http://127.0.0.1:8000/test/
     
    
    表格方式:AdminRenderer
    
    访问URL:
    
    	http://127.0.0.1:8000/test/?format=admin
    	http://127.0.0.1:8000/test.admin
    	http://127.0.0.1:8000/test/
     
    
    form表单方式:HTMLFormRenderer
    
    访问URL:
    
    	http://127.0.0.1:8000/test/?format=form
    	http://127.0.0.1:8000/test.form
    	http://127.0.0.1:8000/test/
     
    
  • 相关阅读:
    LeetCode 227. Basic Calculator II
    LeetCode 224. Basic Calculator
    LeetCode 103. Binary Tree Zigzag Level Order Traversal
    LeetCode 102. Binary Tree Level Order Traversal
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode 169. Majority Element
    LeetCode 145. Binary Tree Postorder Traversal
    LeetCode 94. Binary Tree Inorder Traversal
    LeetCode 144. Binary Tree Preorder Traversal
  • 原文地址:https://www.cnblogs.com/xvchengqi/p/10133387.html
Copyright © 2011-2022 走看看