DRF框架基本组件之视图

REST framework 提供了一个 APIView 类,它继承于 Django 的 View 类。

1,APIView源码分析

#views.py
from rest_framework.views import APIView
 
class BookView(APIView):
     pass
 
#------------------------------------------------
#urls.py
 
url(r'^books/$', views.BookView.as_view()) #项目启动时找到类方法as_view并执行
#APIView部分源码
class APIView(View):
    @classmethod
    def as_view(cls, **initkwargs):   #项目启动时最先在这找到类方法as_view,执行它返回view函数
        view = super(APIView, cls).as_view(**initkwargs)  # 此view函数继承自其父类View
        return csrf_exempt(view)
 
    #执行view函数时,self.dispatch(request, *args, **kwargs)   调用dispatch方法,
    #先从对象的类中找,再去其父类APIView中找,在这能找到dispatch方法,所以最终调用的
    #是APIView类中的dispatch方法,而不再是View类中的dispatch方法!
    def dispatch(self, request, *args, **kwargs):   
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
 
            response = handler(request, *args, **kwargs)
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response

--------------------- 

使用APIView 5种接口的实现:

 url(r'^books/$', views.BookView.as_view()),
 url(r'^books/(\d+)/$', views.BookDetailView.as_view()),
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
 
class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        serializer = BookSerializer(book_list, many=True)
 
        return Response(serializer.data)
 
    def post(self, request):
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)
 
 
class BookDetailView(APIView):
    def get(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).first()
        serializer = BookSerializer(book_obj, many=False)
        return Response(serializer.data)
 
    def put(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).first()
        serializer = BookSerializer(data=request.data, instance=book_obj)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)
 
    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response("ok")
 

2,GenericAPIView / mixin类

2.1  GenericAPIView 类继承于 REST framework 的 APIView 类,为标准列表和详细视图添加了常见的行为。

get_queryset(self) -->默认返回由 queryset 属性指定的查询集;
应该始终使用此方法, 而不是直接访问 self.queryset,因为 REST 会在内部对 self.queryset 的结果进行缓存用于后续所有请求。

get_serializer_class(self) -->返回用于序列化的类。默认返回 serializer_class 属性

 

2.2  mixin 类用于提供基本视图行为的操作

ListModelMixin -->提供一个 list(request, *args, **kwargs) 方法,实现了列出一个查询集;响应数据可以设置分页。

CreateModelMixin -->提供 create(request, *args, **kwargs) 方法,实现创建和保存新模型实例

RetrieveModelMixin -->提供 retrieve(request, *args, **kwargs) 方法,该方法实现在响应中返回现有的模型实例

UpdateModelMixin -->提供 update(request, *args, **kwargs) 方法,实现更新和保存现有模型实例。
还提供了一个 partial_update(request, *args, **kwargs) 方法,它与更新方法类似,只是更新的所有字段都是可选的。这允许支持 HTTP PATCH 请求。

DestroyModelMixin -->提供一个 destroy(request, *args, **kwargs) 方法,实现现有模型实例的删除

 

使用GenericAPIView与mixin 类 5种接口的实现:

#url   
url(r'^books/$', views.BookView.as_view()),
url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),






#view


from rest_framework.mixins import CreateModelMixin,ListModelMixin,DestroyModelMixin,RetrieveModelMixin,UpdateModelMixin
from rest_framework.generics import GenericAPIView
 
class BookView(CreateModelMixin,ListModelMixin,GenericAPIView):
    queryset=Book.objects.all()
    serializer_class=BookSerializers
 
    def get(self,request):
        return self.list(request)
    def post(self,request):
        return self.create(request)
 
 
class BookDetailView(DestroyModelMixin,UpdateModelMixin,RetrieveModelMixin,GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers
 
    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.3  内置通用视图类

class CreateAPIView(CreateModelMixin,GenericAPIView) -->仅用于创建实例;提供一个 post 请求的处理方法

class ListAPIView(ListModelMixin,GenericAPIView) -->仅用于读取模型实例列表。提供一个 get 请求的处理方法

class RetrieveAPIView(RetrieveModelMixin,GenericAPIView) -->仅用于查询单个模型实例。提供一个 get 请求的处理方法

class DestroyAPIView(DestroyModelMixin,GenericAPIView) -->仅用于删除单个模型实例;提供一个 delete 请求的处理方法

class UpdateAPIView(UpdateModelMixin,GenericAPIView) -->仅用于更新单个模型实例。提供 put 和 patch 请求的处理方法

ListCreateAPIView -->既可以获取实例集合,也可以创建实例列表;提供 get 和 post 请求的处理方法
RetrieveUpdateDestroyAPIView -->同时支持查询,更新,删除;提供 get,put,patch 和 delete 请求的处理方法

 

使用内置通用视图 5种接口的实现:

#url
url(r'^books/$', views.BookView.as_view()),
url(r'^books/(?P<pk>\d+)/$', views.BookDetailView.as_view()),



#view
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
 
class BookView(ListCreateAPIView):
    queryset=Book.objects.all
    serializer_class=BookSerializers
 
class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all
    serializer_class = BookSerializers
 

3, 视图集 ViewSet

Django REST framework 允许将一组相关视图的逻辑组合到一个称为 ViewSet 的类中。

ModelViewSet 类继承自 GenericAPIView,并通过混合各种 mixin 类的行为来包含各种操作的实现。

 

使用ModelViewSet 类 5种接口的实现:

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

   from rest_framework.viewsets import ModelViewSet

  class BookModelView(ModelViewSet):
  queryset = Book.objects.all()
  serializer_class = BookSerializer

 

使用路由器

现在我们使用的是ViewSet类而不是View类,那么就不需要自己设计URL路由,通过使用Router类,把视图和资源联系起来的协议和urls会被自动处理。我们只需要使用router来注册合适的视图,剩余的交给router来做就行。 

from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter
from snippets import views

# 实例化一个 router 并用它注册我们的 viewsets 
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet,basename='snippets')
router.register(r'users', views.UserViewSet , basename='users')
# API URLs 现在由 router 自动配置. urlpatterns = [ url(r'^', include(router.urls)) ]

register()函数有两个必要参数:

 

prefix:      字首,用来表示一系列的urls

viewset:   viewset class

可选的参数:

base_name:   用来生成urls名字,如果viewset中没有包含queryset, base_name一定要有

 

posted on 2019-06-15 23:28  Orvis  阅读(193)  评论(0编辑  收藏  举报

导航