Component view

Component view

Basic View

routing

    url(r'^publish/$', views.PublishView.as_view()),
    url(r'^publish/(?P<pk>\d+)/',views.PublishDetailView.as_view()),

serializer.py

from app01 import models
class PublishSerializers(serializers.ModelSerializer):
    class Meta:
        model=models.Publish
        fields='__all__'

view.py

class PublishView(APIView):

    def get(self, request):
        publish_list = models.Publish.objects.all()
        bs = PublishSerializers(publish_list, many=True)
        # 序列化数据

        return Response(bs.data)

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

        bs=PublishSerializers(data=request.data)
        if bs.is_valid():
            bs.save()  # 生成记录
            return Response(bs.data)
        else:

            return Response(bs.errors)

class PublishDetailView(APIView):
    def get(self,request,pk):
        publish_obj=models.Publish.objects.filter(pk=pk).first()
        bs=PublishSerializers(publish_obj,many=False)
        return Response(bs.data)
    def put(self,request,pk):
        publish_obj = models.Publish.objects.filter(pk=pk).first()

        bs=PublishSerializers(data=request.data,instance=publish_obj)
        if bs.is_valid():
            bs.save() # update
            return Response(bs.data)
        else:
            return Response(bs.errors)
    def delete(self,request,pk):
        models.Publish.objects.filter(pk=pk).delete()

        return Response("")

mixin class and the class to write generice view

ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

Five class encapsulates all the investigation, a new record | a check, update, delete, five methods

But the use of these five methods get_serializer, get_object other methods are in class GenericAPIView

And GenericAPIView serializer_class parameters or classes need queryset

So we just have to let the view class inherits the five classes and GenericAPIView class combination can achieve a simple CRUD interface

views.py

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)

 This time, we only need to provide queryset and serializer_class two parameters, a mixin class package will help us following data processing, we call the corresponding method and its return value can be returned,

However, note that if you use this method, urls.py id corresponding to the url death called pk, as follows:

url(r'^publishes/$', views.PublishView.as_view()),
url(r'^publishes/(?P<pk>\d+)/$', views.PublishDetailView.as_view()),

But even if we use this package, there are still a lot of code repetition, all, rest_framework gave us to do a layer package

使用generics 下ListCreateAPIView,RetrieveUpdateDestroyAPIView

ListCreateAPIView class

Inherited ListModelMixin, CreateModelMixin and GenericAPIView

Methods to achieve the get and post member in the class code and returns the serialization of the

RetrieveUpdateDestroyAPIView类

继承了RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin和GenericAPIView

Get achieved in the class code thereof, (put, patch), delete method and return the serialization of the

So we have the following wording

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

In this way, the code a lot clearer, however, this method is still a model table is divided into two views, then, is there a way to be able to merge them together?

Use ModelViewSet

routing:

    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'})),

views.py

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

Custom method correspond to different request method

url.py

    url(r'^aa/$', views.PublishView.as_view({'get': 'aaa'})),
    url(r'^bb/$', views.PublishView.as_view({'get': 'bbb'})),

views.py

from rest_framework.viewsets import  ViewSetMixin
from rest_framework.views import  APIView
# ViewSetMixin 重写了as_view方法
class Test(ViewSetMixin,APIView):

    def aaa(self,request):
        return Response()
    def bbb(self,request):
        return Response()

Source code analysis

Common CBV the view class as_view () is not a parameter passing, ViewSetMixin rewrite method as_view

rest_framework>viewsets>ViewSetMixin

Part of the source code as follows:

@classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        """
        Because of the way class based views create a closure around the
        instantiated view, we need to totally reimplement `.as_view`,
        and slightly modify the view function that is created and returned.
        """
       ......
    # 若继承了ModelViewSet类必须在路由中传入actions
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")

     ......
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            # We also store the mapping of request methods to actions,
            # so that we can later set the action attribute.
            # eg. `self.action = 'list'` on an incoming GET request.
            self.action_map = actions

            # Bind methods to actions
            # This is the bit that's different to a standard view
            # 将视图类中的action方法与请求方式绑定 
            # 不同的请求方式对应出发不同的方法
            for method, action in actions.items():
                handler = getattr(self, action)
                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

            # And continue as usual
            return self.dispatch(request, *args, **kwargs)

Inheritance of the classes in the primary key

Each class relationship analysis

First, we have to look at, when we do not inherit the View class defines class view themselves, DRF to oh they provide a wealth of several classes inherit from the View class

Base class: APIView

APIView is the base class for all views provided by the REST framework, inherited from the parent class View Django.

APIView and View differs in that:

Passed to the view method is REST framework Request object, rather than the object of Django HttpRequeset;
view showing the method may return REST framework Response object, the view in response to the data set (the render) conform to the format required by the front end;
any exceptions are APIException It is captured, and information into appropriate response;
performing dispatch () prior to distribution, will request authentication, permission checks, the flow control.
Support defined attributes:

authentication_classes list or Ganso, authentication type
permissoin_classes list or Ganso, permission checks class

throttle_classes lists or tuples, flow control class

In APIViewor conventional process and still view class defines methods to achieve get (), post () requests another embodiment.

2.基类:GenericAPIView

提供的关于序列化器使用的属性与方法

GenericAPIView
继承自APⅣew,主要增加了操作序列化器和数
据库查询的方法,作用是为下面Mixn扩展类的
执行提供方法支持。通常在使用时,可搭配一个
或多个Min扩展类
指明视图使用的序列化器
1通过属性: serializer_ class
2通过方法: get serializer_class(self
get serializer(self, args, * kwargs)
数据库查询的属性与方法
指明使用的数据查询集
1通过属性: queryset
2通过方法: get queryset(se)
get object(self)

配合GenericAPIView使用的几个扩展类

我们发现前边的两个父类还需要进行函数的定义去处理不同的请求,这样我们还得在函数里边实现查询集以及序列化器的指定,工作量仍然很大。怎么解决呢?

GenericAPIView的五个扩展类给我们提供了五个方法分别进行增删改查的不同操作,这样我们就不用写那么多函数啦!!

搭配GenericAPIView使用

1.ListModelMixin: 提供list方法快速实现列表视图

2.CreateModelMixin: 提供create方法快速实现创建资源的视图

3.RetrieveModelMixin 提供retrieve方法,可以快速实现返回一个存在的数据对象(需要传入pk)

4.UpdateModelMixin 提供update方法,可以快速实现更新一个存在的数据对象。 提供partial_update方法,可以实现局部更新

5.DestroyModelMixin 提供destroy方法,可以快速实现删除一个存在的数据对象

1.CreateAPIView(等价于GenericAPIView+CreateModelMixin) 提供 post 方法 继承自: GenericAPIView、CreateModelMixin

2.ListAPIView 提供 get 方法 继承自:GenericAPIView、ListModelMixin

3.RetrieveAPIView 提供 get 方法 继承自: GenericAPIView、RetrieveModelMixin

4.DestoryAPIView 提供 delete 方法 继承自:GenericAPIView、DestoryModelMixin

5.UpdateAPIView 提供 put 和 patch 方法 继承自:GenericAPIView、UpdateModelMixin

6.RetrieveUpdateAPIView 提供 get、put、patch方法 继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

7.RetrieveUpdateDestoryAPIView 提供 get、put、patch、delete方法 继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

所以代码中的mixins.RetrieveModelMixin, GenericAPIView可以写成RetrieveAPIView

Guess you like

Origin www.cnblogs.com/9527mwz/p/11200592.html