def 视图家族

视图家族:

基本视图 (APIView):

--> 主要就是通过视图类APIView,里面的逻辑都需要自己去实现,需要自己写接口 (10大接口)

子路由:

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^books/$', views.BookAPIView.as_view()),
    url(r'^books/(?P<pk>.*)/$', views.BookAPIView.as_view()),
]

视图层:

from rest_framework import views
from . import models, serializers
from utils.response import APIResponse

class BookAPIView(views.APIView):
     def post(self, request, *args, **kwargs):
        # 把单增也转换为群增
        request_data = request.data
        if isinstance(request_data, dict):
            data = [request_data, ]
        elif isinstance(request, list):
            data = request_data
        else:
            return APIView(1, '数据格式有误')
        
        book_ser = serializers.BookV2ModelSerializer(data=data, many=True)
        if book_ser.is_valid():
            book_obj_list = book_ser.save()
            results = serializers.BookV2ModelSerializer(book_obj_list, many=True).data
            return APIResponse(0, 'ok', results=results)
        else:
            return APIResponse(1, '添加失败', results=book_ser.errors)

视图工具类 (mixins):

介绍:

RetrieveModelMixin:     retrieve 方法实现了获取一个对象  (单查)

ListModelMixin:         list方法实现了获取多个对象      (群查)

CreateModelMixin:       create方法实现了增加一个对象     (单增)

UpdateModelMixin:       update方法实现了单整体更新,      (put 改)
                        partial_update实现了单局部更新   (patch 改)

DestroyModelMixin:      destory方法实现了单独删除        (单删)

-----》 一般结合generics工具视图使用

    继承工具类可以简化请求函数的实现体,但是必须继承GenericAPIView,需要GenericAPIView类提供的几个类属性和方法

    工具类的工具方法返回值都是Response类型对象,如果要格式化数据格式再返回给前台,可以通过 response.data 拿到工具方法返回的Response类型对象的响应数据

子路由:

urlpatterns = [
    url(r'^v3/books/$', views.BookMixinGenericAPIView.as_view()),
    url(r'^v3/books/(?P<pk>.*)/$', views.BookMixinGenericAPIView.as_view()),
]

视图层:

from rest_framework.mixins import ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin
class BookMixinGenericAPIView(ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericAPIView):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer

    def get(self, request, *args, **kwargs):
        if 'pk' in kwargs:
            response = self.retrieve(request, *args, **kwargs)
        else:
            # mixins提供的list方法的响应对象是Response,想将该对象格式化为APIResponse
            response = self.list(request, *args, **kwargs)
        # response的数据都存放在response.data中
        return APIResponse(results=response.data)

    def post(self, request, *args, **kwargs):
        response = self.create(request, *args, **kwargs)
        return APIResponse(results=response.data)

    def put(self, request, *args, **kwargs):
        response = self.update(request, *args, **kwargs)
        return APIResponse(results=response.data)

    def patch(self, request, *args, **kwargs):
        response = self.partial_update(request, *args, **kwargs)
        return APIResponse(results=response.data)

工具视图 (generics):

介绍:

GenericAPIView:

GenericAPIView,是generics家族的基类,主要帮我们把qureyset和serializer_class封装成了属性

 1)工具视图都是GenericAPIView的子类,且不同的子类继承了不听的工具类,重写了请求方法
 2)工具视图的功能如果直接可以满足需求,只需要继承工具视图,提供queryset与serializer_class即可

GenericAPIView基类:

GenericAPIView是继承APIView的,使用完全兼容APIView

重点:GenericAPIView在APIView基础上完成了哪些事
    1)get_queryset():从类属性queryset中获得model的queryset数据
    2)get_object():从类属性queryset中获得model的queryset数据,再通过有名分组pk确定唯一操作对象
    3)get_serializer():从类属性serializer_class中获得serializer的序列化类

视图层:

from rest_framework.generics import GenericAPIView
class BookGenericAPIView(GenericAPIView):
    
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer
    # 自定义主键的 有名分组 名
    lookup_field = 'pk'                         # 源码内与之对应
    # 群取
    # def get(self, request, *args, **kwargs):
    #     book_query = self.get_queryset()
    #     book_ser = self.get_serializer(book_query, many=True)
    #     book_data = book_ser.data
    #     return APIResponse(results=book_data)

    # 单取
    def get(self, request, *args, **kwargs):
        book_query = self.get_object()
        book_ser = self.get_serializer(book_query)
        book_data = book_ser.data
        return APIResponse(results=book_data)

注意: 不能同时出现单 | 群取


from rest_framework.generics import ListCreateAPIView, UpdateAPIView
class BookListCreatePIView(ListCreateAPIView, UpdateAPIView):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer

视图集 (viewsets):

子路由:

1)视图集都是优先继承ViewSetMixin类,再继承一个视图类(GenericAPIView或APIView)
      GenericViewSet、ViewSet
        
2)ViewSetMixin提供了重写的as_view()方法,继承视图集的视图类,配置路由时调用as_view()必须传入 请求名-函数名 映射关系字典

eg: url(r'^v5/books/$', views.BookGenericViewSet.as_view({'get': 'my_get_list'})),
表示get请求会交给my_get_list视图函数处理


urlpatterns = [
    url(r'^v5/books/$', views.BookGenericViewSet.as_view({'get': 'my_get_list'})),
    url(r'^v5/books/(?P<pk>.*)/$', views.BookGenericViewSet.as_view({'get': 'my_get_obj'})),
]

视图层:

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:

    list() 提供一组数据
    retrieve() 提供单个数据
    create() 创建数据
    update() 保存数据
    destory() 删除数据
    ViewSet视图集类不再实现get()、post()等方法,而是实现动作action如 list() 、create() 等

视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。



from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
class BookGenericViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer

    def my_get_list(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def my_get_obj(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

设置路由时:
    urlpatterns = [
    url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
    url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]

action属性:

在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个

def get_serializer_class(self):
    if self.action == 'create':
        return OrderCommitSerializer
    else:
        return OrderDataSerializer

常用视图集父类:

(1)ViewSet
继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

(2)GenericViewSet
继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。

(3)ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

(4)ReadOnlyModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin

添加自定义动作需要使用rest_framework.decorators.action装饰器。

以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。

action装饰器可以接收两个参数:

methods: 该action支持的请求方式,列表传递
detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
True 表示使用通过URL获取的主键对应的数据对象
False 表示不使用URL获取主键


  @action(methods=['get'], detail=False)
    def latest(self, request):
        """
        返回最新的图书信息
        """
        book = BookInfo.objects.latest('id')
        serializer = self.get_serializer(book)
        return Response(serializer.data)

    # detail为True,表示要处理具体与pk主键对应的BookInfo对象
    @action(methods=['put'], detail=True)
    def read(self, request, pk):
        """
        修改图书的阅读量数据
        """
        book = self.get_object()
        book.bread = request.data.get('read')
        book.save()
        serializer = self.get_serializer(book)
        return Response(serializer.data)
    
    
# urls.py

    
urlpatterns = [
    url(r'^books/(?P<pk>\d+)/$', views.BookInfoViewSet.as_view({'get': 'retrieve'})),
    url(r'^books/(?P<pk>\d+)/read/$', views.BookInfoViewSet.as_view({'put': 'read'})),
]

路由Router:

路由Router
    对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。

REST framework提供了两个router:

    SimpleRouter
    DefaultRouter

创建router 对象:
    from rest_framework import routers

    router = routers.SimpleRouter()
    router.register(r'books', BookInfoViewSet, base_name='book')


register(prefix, viewset, base_name)

    prefix 该视图集的路由前缀
    viewset 视图集
    base_name 路由名称的前缀

注意: prtfix : 前缀后不用加换行符,会自动加

添加路由数据方式:

# 方式一:
urlpatterns = [
    ...
]
urlpatterns += router.urls

#方式二:
urlpatterns = [
    ...
    url(r'^', include(router.urls))
]


#2.视图集中包含附加action:

class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    @action(methods=['get'], detail=False)
    def latest(self, request):
        ...

    @action(methods=['put'], detail=True)
    def read(self, request, pk):
        ...

    DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据

路由router形成URL的方式:

SimpleRouter:

DefaultRouter:

猜你喜欢

转载自www.cnblogs.com/shaozheng/p/12121277.html
def