DRF-视图类组件

补充

       GET 
    books-------->查看数据--------------------> 返回所有数据列表 :[{},{},{}]
      POST
    books-------->添加数据--------------------->返回添加数据 :{}
      PUT
    books/1------->更新pk=1的数据--------------->返回更新后的数据: {}
      Delete
    books/1-------> 删除pk=1的数据-------------->返回空
      GET
    books/1------->查看单条数据 --------------->返回查看的单条数据 {}

普通版

缺点:缺点再实际工作中我们可能建多个表,导致代码过于冗余,所以我们要进行进一步封装。

from django.shortcuts import render,HttpResponse

from django.views import View
# Create your views here.
# 导入djangorestframework
# 当前访问视图类下设置解析方式
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from app01.models import *
from rest_framework import serializers
from rest_framework.response import Response


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book
        # fields=["title","price"]
        fields="__all__"

    def get_authors(self,obj):
        ret=[]
        for i in obj.authors.all():
            ret.append(i.name)
        return ret


class LoginView(APIView):
    parser_classes = [JSONParser]
    def get(self,request):
        book_list = Book.objects.all()
        serializer = BookSerializer(book_list,many=True)
        return Response(serializer.data)
    def post(self,request):
        print('body',request.body)
        print(request.data)
        print('data',request.data)
        return HttpResponse('OK')

class SLoginView(APIView):
    def get(self,request,id):
        my_obj = Book.objects.get(pk=id)
        serializer = BookSerializer(my_obj, many=False)
        return Response(serializer.data)
        pass
    def put(self,request,id):
        my_obj = Book.objects.get(pk=id)
        serializer = BookSerializer(data=request.data,instance=my_obj)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)
    def delete(self,request,id):
        my_obj = Book.objects.get(pk=id).delete()
        return Response("")

 

第一步封装---对里面的数据操作进行封装

url中

url(r'^authors/$', views.AuthorsView.as_view()),
url(r'^authors/(?P<pk>\d+)/', views.SAuthorsView.as_view()),

 

视图函数中

from rest_framework import generics

from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin

from rest_framework import generics



class PublishView(ListModelMixin,CreateModelMixin,generics.GenericAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    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 SPublishView(UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,generics.GenericAPIView):

    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    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)

第二步封装,对两个类中的方法进行封装,然后把两个视图合为一个视图再进行封装

url中

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

视图中

from rest_framework.viewsets import ModelViewSet

class AuthorsView(ModelViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer

 

对封装后的视图类组件的源码解析

1 启动Django,执行AuthorsView.as_view 找继承最近的as_view
    url(r'^authors/$', views.AuthorsView.as_view({"get":"list","post":"create"})),
    url(r'^authors/(?P<pk>\d+)/', views.AuthorsView.as_view({"get":"retrieve","delete":"destroy","put":"update"})),

2 在AuthorsView,下找as_view方法
        class AuthorsView(ModelViewSet):
            queryset = Author.objects.all()
            erializer_class = AuthorSerializer
    没找到,去父类ModelViewSet下找

3 在ModelViewSet,下找as_view方法
    class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):pass
    
    没找到,去父类GenericViewSet下找
4 在GenericViewSet,下找as_view方法
    class GenericViewSet(ViewSetMixin, generics.GenericAPIView):pass
    没找到,去父类ViewSetMixin下找
//******找到我们要的as_view方法
5 在ViewSetMixin,下找as_view方法,我们找到了as_view()
    class ViewSetMixin(object):
        @classonlymethod
        # *****这里我们把url中的as_view参数{"get":"retrieve","delete":"destroy","put":"update"}传给了actions,开始关注actions
        def as_view(cls, actions=None, **initkwargs):
            def view(request, *args, **kwargs):
                for method, action in actions.items():
                    handler = getattr(self, action)
                    setattr(self, method, handler)
                return    self.dispatch(request, *args, **kwargs)
            return csrf_exempt(view)
        我们找到了as_view() 然后返回view
        // ******这里开始浏览器请求数据
        当浏览器访问时我们执行view()
            handler = getattr(self, action) 我们得到self.retrieve 这个方法
            setattr(self, method, handler)  我们self.get = self.retrieve 我们把方法赋给相应的请求
            return    self.dispatch(request, *args, **kwargs) 这里我们又回到APIview下的内容分发了
6 在APIview中的dispatch中
    def dispatch(self, request, *args, **kwargs):
        # *****进行内容分发,self.get,self.put...由于在步骤5我们又对他们进行了赋值,相当于self.retrieve,self.update...
        handler = getattr(self, request.method.lower(),self.http_method_not_allowed)
        # 这里执行函数retrieve().......
        response = handler(request, *args, **kwargs)
        return self.response

 

posted @ 2018-09-19 16:09  神秘嘉宾7m  阅读(144)  评论(0编辑  收藏  举报