drf视图

不使用drf视图

#在下面的这些代码中,存在很多代码重复
from rest_framework.views import APIView
from app01.models import *
from app01.mySer import *
from django.http import JsonResponse

class PublishView(APIView):

    def get(self, request):     #获取所有数据
        publish_list = Publish.objects.all()
        bs = PublishSerializers(publish_list, many=True)    #PublishSerializers自己写的序列化

        return JsonResponse(bs.data,safe=False)

    def post(self, request):     #添加纪录
        # 添加一条数据
        print(request.data)

        bs = PublishSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成记录
            return JsonResponse(bs.data,safe=False)
        else:

            return JsonResponse(bs.errors,safe=False)


class PublishDetailView(APIView):
    def get(self, request, pk):      #获取单条数据
        publish_obj = Publish.objects.filter(pk=pk).first()
        bs = PublishSerializers(publish_obj, many=False)
        return JsonResponse(bs.data,safe=False)

    def put(self, request, pk):    #修改单条
        publish_obj = Publish.objects.filter(pk=pk).first()

        bs = PublishSerializers(data=request.data, instance=publish_obj)
        if bs.is_valid():
            bs.save()  # update
            return JsonResponse(bs.data)
        else:
            return JsonResponse(bs.errors)
 
    def delete(self, request, pk):  #删除一条数据
        Publish.objects.filter(pk=pk).delete()

        return JsonResponse("")
View Code

还是不使用drf,但进行了封装

#自己写两个类,把重复代码抽出来
class List:    #列表,拿多条
    #把获取多条的get抽过来
    def list(self):              
        publish_list = Publish.objects.all()
        bs = PublishSerializers(publish_list, many=True)  # PublishSerializers自己写的序列化

        return JsonResponse(bs.data, safe=False)


class Create:
  #把post方法抽过来
    def create(self,request):      
        bs = PublishSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成记录
            return JsonResponse(bs.data, safe=False)
        else:
            return JsonResponse(bs.errors, safe=False)

------------------------------------------------------------
#使用的时候
class PublishView(APIView,List,Create):

    def get(self, request):  # 获取所有数据
        return self.list(request)      #当请求来到这时,在当前找不到list方法,然后去父类找,执行,并拿到结果

    def post(self, request):
        return self.create(request)#同理,请求来了,去父类中找create方法

---------------------------------------------------
#但是
#上面这种方式只能对应Publish表,PublishSerializers序列化组件,写死了
class BookhView(APIView, List, Create)    
                                          #
    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)
不够精简的封装
#把写死的地方,通过传值写活

class List:    #列表,拿多条
    def list(self):    #把获取多条的get抽过来
        # publish_list = Publish.objects.all()     #原来的方式
        # bs = PublishSerializers(publish_list, many=True

        queryset = self.queryset               #把原本写死的东西写活
        bs = self.serializers(queryset, many=True)  #把原本写死的东西写活

        return JsonResponse(bs.data, safe=False)

class Create:
    def create(self,request):      #把post方法抽过来
        print(request.data)
        # bs = PublishSerializers(data=request.data)
        bs = self.serializers(data=request.data)         #把原本写死的东西写活
        if bs.is_valid():
            bs.save()  # 生成记录
            return JsonResponse(bs.data, safe=False)
        else:
            return JsonResponse(bs.errors, safe=False)

-------------------------------------------
#使用
class PublishView(APIView,List,Create):      #前边自己写的两个类,是怎么处理,一定要与这里的怎么用区分开,条理清晰
    queryset= Publish.objects.all()         #需要用哪个模型表,就传给queryset
    serializers=PublishSerializers          #需要用哪个序列化组件,就把谁赋给serializers
    def get(self, request):  # 获取所有数据
        return self.list(request)      #当请求来到这时,在当前找不到list方法,然后去父类找,执行,并拿到结果

    def post(self, request):
            return self.create(request)#同理,请求来了,去父类中找create方法


class BookhView(APIView, List, Create)     #此时就比较方便了,再来多少都行,只需要把模型表
    queryset= Book.objects.all()         #需要用哪个模型表,就传给queryset
    serializers=BookSerializers          #需要用哪个序列化组件,就把谁赋给serializers
    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)
升级版封装

使用drf封装的类

先看源码(拿两个典型的,其他的类似)

#GenericAPIView它继承了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

    def get_queryset(self):
    def get_object(self):
    def get_serializer(self, *args, **kwargs):
    def get_serializer_class(self)     
    def get_serializer_context(self)
    def filter_queryset(self, queryset)
GenericAPIView源码
class ListModelMixin(object):

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())  #类似于自己写的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)


queryset     #这些都需要去GenericAPIView中
get_queryset
filter_queryset
ListModelMixin源码

使用

#GenericAPIView继承了APIView,只不过添加了几个方法

#拿多个
class PublishView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset= Publish.objects.all()
    serializer_class=PublishSerializers
    def get(self, request):
        return self.list(request)   

#请求来到这里,list方法,自己,没有,去父类,在ListModelMixin中找到,父类中需要的
filter_queryset,paginate_queryset,get_serializer先来自己这找,自己这没有,去父类中,在GenericAPIView中找到

    def post(self, request):      #添加用CreateModelMixin
        return self.create(request)   #同样道理,create去父类中找,父类中需要的其他参数,去另外父类中找


---------------------------------------------------------
#拿一个的方法,道理同上
from rest_framework.mixins import ListModelMixin,RetrieveModelMixin,RetrieveModelMixin,DestroyModelMixin
from rest_framework.generics import GenericAPIView


class PublishDetailView(APIView):
    queryset= Publish.objects.all()
    serializer_class=PublishSerializers
    def get(self, request,pk):               #RetrieveModelMixin
        return self.retrieve(self, request, pk)


    def post(self, request,pk):            #RetrieveModelMixin
        return self.update(request,pk)


    def delete(self, request, pk):       #DestroyModelMixin
        return self.destroy(request,pk)




------------------------------------------
#这种方法仍然存在重复代码,取多个,取一个都要指定
    queryset= Publish.objects.all()
    serializer_class=PublishSerializers
View Code

使用drf升级版(最终版)

# 上面发现仍有重复代码
# queryset = Publish.objects.all()
# serializers = PublishSerializers
from rest_framework.viewsets import ModelViewSet
class PublishDetailView(ModelViewSet):    #只需要写这一个,5个接口都有了
    queryset= Publish.objects.all()
    serializer_class=PublishSerializers


#不过路由需要传参
    url(r'^books/$', views.Book.as_view({'get': 'list', 'post': 'create'})),
    url(r'^books/(?P<pk>d+)/$',views.Book.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),

 这种情况不建议使用,一般自己写类,继承魔法类,自己在类中实现功能

 

#1、ModelViewSet
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,           #前四个已经了解
                   GenericViewSet):      #重点读这个源码


2、#来到GenericViewSet
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):

    pass     #源码的pass
#它继承了ViewSetMixin




#3、来看ViewSetMixin
#url(r'^books/$', views.Book.as_view({'get': 'list', 'post': 'create'})),
#url(r'^books/(?P<pk>d+)/$',views.Book.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),


class ViewSetMixin(object):    #路由的参数给actions
    def as_view(cls, actions=None, **initkwargs):

        def view(request, *args, **kwargs):  #重写了view方法
              #{'get': 'list', 'post': 'create'}
             #如果method=get  ,action = list
            for method, action in actions.items():    #解压取值
                #handler 就是list的内存地址
                handler = getattr(self, action)
                 #把list的内存地址,赋值给了get,    
                setattr(self, method, handler)
那么如果是{'get': 'retrieve'},,直接把retrieve赋值给get
ViewSetMixin魔法类
#可以实现在一个类中,路由地址不一样




from rest_framework.viewsets import ViewSetMixin
#注意前后顺序,ViewSetMixin一定放在前边,为了执行它的as_view方法
class TestAll(ViewSetMixin,APIView):
    def text1(self,request):
        return HttpResponse('text1')

    def text2(self,request):
        return HttpResponse('text2')

    def text3(self,request):
        return HttpResponse('text3')

    def text4(self,request):
        return HttpResponse('text4')


------------------------------------------------
urls
    url(r'^text1/$', views.TestAll.as_view({'get': 'tet1'})),
    url(r'^text1/$', views.TestAll.as_view({'get': 'tet2'})),
    url(r'^text1/$', views.TestAll.as_view({'get': 'tet3'})),
    url(r'^text1/$', views.TestAll.as_view({'get': 'tet4'})),
魔法类用法
原文地址:https://www.cnblogs.com/pdun/p/11257059.html