Django的DRF(二):APIView(一级视图)、GenericAPIView(二级视图)、三级视图、ViewSets(视图集)、Router(路由)

一.APIView(一级视图)

DRF的APIViews官网:https://www.django-rest-framework.org/api-guide/views/
APIView是REST framework提供的所有视图的基类,继承自Django的View父类。

APIViews的特点:
1)集成自View           2)提供了自己的request对象
3)提供了自己的response对象    4)提供了认证,权限,限流等功能

1.Request与Response

(1)Request
REST framework 传入视图的request对象不再是Django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。

REST framework 提供了Parser解析器,在接收到请求后会自动根据Content-Type指明的请求数据类型(如JSON、表单等)将请求数据进行parse解析,解析为类字典对象保存到Request对象中。

Request对象的数据是自动根据前端发送数据的格式进行解析之后的结果。

无论前端发送的哪种格式的数据,我们都可以以统一的方式读取数据。
常用属性:
1).query_params
request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。
2).data
request.data 返回解析之后的请求体数据。类似于Django中标准的request.POST和 request.FILES属性,但提供如下特性:
  包含了解析之后的文件和非文件数据
  包含了对POST、PUT、PATCH请求方式解析后的数据
  利用了REST framework的parsers解析器,不仅支持表单类型数据,也支持JSON数据
示例:
view.py:

# 定义类,集成APIView
from django.http import HttpResponse
from rest_framework.views import APIView

class BookAPIView(APIView):
    def get(self, request):
        # 获取APIView中的get请求参数
        print(request.query_params)
        return HttpResponse('get')
    def post(self,request):
        # 获取APIView中的post请求参数
        print(request.data)
        return HttpResponse('post')   

子路由:

from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^books/$',views.BookAPIView.as_view())
]

根路由:

url(r'^', include('Book.urls'))

运行结果:
在这里插入图片描述

在这里插入图片描述
(2)Response
REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型。
构造方式:

Response(data, status=None, template_name=None, headers=None, content_type=None)

data数据不要是render处理之后的数据,只需传递python的内建类型数据即可,REST framework会使用renderer渲染器处理data。

data不能是复杂结构的数据,如Django的模型类对象,对于这样的数据我们可以使用Serializer序列化器序列化处理后(转为了Python字典类型)再传递给data参数。

参数说明:
  data: 为响应准备的序列化处理后的数据;
  status: 状态码,默认200;
  template_name: 模板名称,如果使用HTMLRenderer 时需指明;
  headers: 用于存放响应头信息的字典;
  content_type: 响应数据的Content-Type,通常此参数无需传递,REST framework会根据前端所需类型数据来设置该参数。
示例

from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

class BookAPIView(APIView):
    def get(self, request):
        return Response([{'name':'YFater'},{'age':18}],status=status.HTTP_200_OK)

运行结果:
在这里插入图片描述

使用Response的好处:
1.使用一个类,就可以替代View中的各种类型的Response(HTTPResponse,JsonResponse…)
2.可以配合状态码status使用

(3)状态码
为了方便设置状态码,REST framewrok在rest_framework.status模块中提供了常用状态码常量。
1)信息告知 - 1xx
HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS
2)成功 - 2xx
HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS
3)重定向 - 3xx
HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT
4)客户端错误 - 4xx
HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
5)服务器错误 - 5xx
HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

2.APIView实现列表视图

serializers.py:

from rest_framework import serializers
from Book.models import BookInfo

# 定义书籍模型序列化器
class BookInfoModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = BookInfo,
        fields = '__all__'

view.py:

# 序列化器和APIView实现列表视图
class BookListAPIView(APIView):
    def get(self,request):
        # 查询所有的书籍
        books = BookInfo.objects.all()
        # 将对象列表转换成字典列表
        serializer = BookInfoModelSerializer(instance=books,many=True)
        # 返回响应
        return Response(serializer.data)

    def post(self,request):
        # 获取参数
        data_dict = request.data
        # 创建序列化器
        serializer = BookInfoModelSerializer(data=data_dict)
        # 校验
        serializer.is_valid(raise_exception=True)
        # 入库
        serializer.save()
        # 返回响应
        return Response(serializer.data,status=status.HTTP_201_CREATED)

子路由:

url(r'^books/$',views.BookListAPIView.as_view()),

运行结果:
在这里插入图片描述
在这里插入图片描述

3.APIView实现详情视图

views.py:

# 序列化器和APIView实现详情视图
class BookDetailAPIView(APIView):
    def get(self,request,book_id):
        #1 获取书籍
        book = BookInfo.objects.get(pk=book_id)
        #2 创建序列化对象
        serializer = BookInfoModelSerializer(instance=book)
        #3 返回响应
        return Response(serializer.data,status=status.HTTP_200_OK)
    def put(self,request,book_id):
        # 获取数据,获取对象
        dict_data = request.data
        book = BookInfo.objects.get(pk=book_id)
        # 创建序列化对象
        serializer = BookInfoModelSerializer(instance=book,data=dict_data)
        # 校验,入库
        serializer.is_valid(raise_exception=True)
        serializer.save()
        #返回响应
        return Response(serializer.data,status=status.HTTP_201_CREATED)
    def delete(self,request,book_id):
        BookInfo.objects.get(pk=book_id).delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

子路由:

url(r'^books/(?P<book_id>\d+)/$',views.BookDetailAPIView.as_view()),

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二.GenericAPIView(二级视图)

DRF的GenericAPIView官网:https://www.django-rest-framework.org/api-guide/generic-views/#genericapiview
GenericAPIView继承自APIVIew类,为列表视图和详情视图,添加了常用的行为和属性;通常使用时,可搭配一个或多个Mixin扩展类。

1.定义的属性和方法

1)支持定义的属性:
  列表视图与详情视图通用:
    queryset 列表视图的查询集
     serializer_class 视图使用的序列化器
  列表视图使用:
    pagination_class 分页控制类
    filter_backends 过滤控制后端
  详情页视图使用:
    lookup_field 查询单一数据库对象时使用的条件字段,默认为’pk’
    lookup_url_kwarg 查询单一数据时URL中的参数关键字名称,默认与look_field相同
2)提供的方法:
  列表视图与详情视图通用:
    get_queryset(self):返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写
    get_serializer_class(self):返回序列化器类,默认返回serializer_class,可以重写
    get_serializer(self, args, *kwargs):返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。
    注意,在提供序列化器对象的时候,REST framework会向对象的context属性补充三个数据:request、format、view,这三个数据对象可以在定义序列化器时使用。
  详情视图使用: 
    get_object(self): 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在试图中可以调用该方法获取详情信息的模型类对象。
    若详情访问的模型类对象不存在,会返回404。
    该方法会默认使用APIView提供的check_object_permissions方法检查当前对象是否有权限被访问。

2.GenericAPIView实现列表视图

views.py:

# 使用二级视图GenericAPIView实现列表视图
class BookListGenericAPIView(GenericAPIView):
    # 提供公共的属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    def get(self, request):
        # 查询所有的书籍(2种)
        # books = self.queryset
        books = self.get_queryset()
        # 将对象列表转换成字典列表(3种方法)
        # serializer = self.serializer_class(instance=books, many=True)
        # serializer = self.get_serializer_class()(instance=books, many=True)
        serializer = self.get_serializer(instance=books, many=True)
        # 返回响应
        return Response(serializer.data)

    def post(self, request):
        # 获取参数
        data_dict = request.data
        # 创建序列化器
        serializer = self.get_serializer(data=data_dict)
        # 校验
        serializer.is_valid(raise_exception=True)
        # 入库
        serializer.save()
        # 返回响应
        return Response(serializer.data, status=status.HTTP_201_CREATED)

子路由:

url(r'^generic_apiview_books/$', views.BookListGenericAPIView.as_view()),

运行结果:
在这里插入图片描述
在这里插入图片描述
由上,我们可以发现代码的可重复利用性大,如果我们想将书籍序列化器改为英雄序列化器,只需要将提供的公共属性中修改为英雄模型和英雄序列化器一处即可。

3.GenericAPIView实现详情视图

views.py:

# 使用二级视图GenericAPIView实现详情视图
class BookDetailGenericAPIView(GenericAPIView):
    # 提供通用的属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer
    def get(self, request, pk):
        # 1 获取书籍
        # get_object()根据pk到queryset中取出书籍对象
        book = self.get_object()
        # 2 创建序列化对象
        serializer = self.get_serializer(instance=book)
        # 3 返回响应
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk):
        # 获取数据,获取对象
        dict_data = request.data
        book = self.get_object()
        # 创建序列化对象
        serializer = self.get_serializer(instance=book, data=dict_data)
        # 校验,入库
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 返回响应
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request, pk):
        self.get_object().delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

子路由:

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

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注意:在系统默认情况下,lookup_field参数为pk,如果想改变参数,可设置lookup_field=‘id’ 或者 lookup_url_kwarg=‘book_id’

views.py:

# 使用二级视图GenericAPIView实现详情视图
class BookDetailGenericAPIView(GenericAPIView):
    # 提供通用的属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer
    # lookup_field = 'id'
    lookup_url_kwarg = 'book_id'

    def get(self, request, book_id):
        # 1 获取书籍
        # get_object()根据pk到queryset中取出书籍对象
        book = self.get_object()
        # 2 创建序列化对象
        serializer = self.get_serializer(instance=book)
        # 3 返回响应
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, book_id):
        # 获取数据,获取对象
        dict_data = request.data
        book = self.get_object()
        # 创建序列化对象
        serializer = self.get_serializer(instance=book, data=dict_data)
        # 校验,入库
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 返回响应
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request, book_id):
        self.get_object().delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

子路由:

url(r'^generic_apiview_books/(?P<book_id>\d+)/$', views.BookDetailGenericAPIView.as_view()),

运行结果:
在这里插入图片描述

4.扩展类(MiXin)

DRF的MiXin官网:https://www.django-rest-framework.org/api-guide/generic-views/#mixins
MiXin的特点:
1.mixin类提供用于提供基本视图行为(列表视图,详情视图)的操作
2.配合二级视图GenericAPIView使用的
常见的mixin类:

类名称提供方法功能
ListModelMiXinlist查询所有的数据
CreateModleMiXincreate创建单个对象
RetrieveModleMiXinretrieve获取单个对象
UpdateModleMiXinupdate更新单个对象
DestroyModleMiXindestroy删除单个对象

(1)ListModelMixin
列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

该Mixin的list方法会对数据进行过滤和分页。
源代码:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        # 过滤
        queryset = self.filter_queryset(self.get_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)

(2)CreateModelMixin
创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。

如果序列化器对前端发送的数据验证失败,返回400错误。

源代码:

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        # 获取序列化器
        serializer = self.get_serializer(data=request.data)
        # 验证
        serializer.is_valid(raise_exception=True)
        # 保存
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

(3)RetrieveModelMixin
详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。

如果存在,返回200, 否则返回404。

源代码:

class RetrieveModelMixin(object):
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        # 获取对象,会检查对象的权限
        instance = self.get_object()
        # 序列化
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

(4)UpdateModelMixin
更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。

同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。

成功返回200,序列化器校验数据失败时,返回400错误。

源代码:

class UpdateModelMixin(object):
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

(5)DestroyModelMixin
删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。

成功返回204,不存在返回404。

源代码:

class DestroyModelMixin(object):
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

5.MiXin与GenericAPIView结合

(1)Mixin和二级视图GenericAPIView,实现列表视图
views.py:

from rest_framework.mixins import ListModelMixin, CreateModelMixin

class BookListMixinGenericAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    # 提供公共的属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

子路由:

url(r'^mixin_generic_apiview_books/$', views.BookListMixinGenericAPIView.as_view()),

运行结果:
在这里插入图片描述
在这里插入图片描述
(2)Mixin和二级视图GenericAPIView,实现详情视图
views.py:

# mixin和二级视图GenericAPIView,实现详情视图
class BookDetailMixinGenericAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    # 提供通用的属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer
    lookup_field = 'id'

    def get(self, request, id):
        return self.retrieve(request)

    def put(self, request, id):
        return self.update(request)

    def delete(self, request, id):
        return self.destroy(request)

子路由:

url(r'^mixin_generic_apiview_books/(?P<id>\d+)/$', views.BookDetailMixinGenericAPIView.as_view()),

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三.通用视图(三级视图)

DRF的Concrete View Classes官网:https://www.django-rest-framework.org/api-guide/generic-views/#concrete-view-classes
以下类是具体的通用视图。如果您使用的是通用视图,那么通常这就是您要使用的级别,除非需要大量的自定义行为。
常见的三级视图:

类名称父类提供方法作用
CreateAPIViewGenericAPIView,CreateModelMixinpost创建单个对象
ListAPIViewGenericAPIView,ListModelMixinget查询所有的数据
RetrieveAPIViewGenericAPIView, RetrieveModelMixinget获取单个对象
DestroyAPIViewGenericAPIView, DestroyModelMixindelete删除单个对象
UpdateAPIViewGenericAPIView, UpdateModelMixinput更新单个对象

1.三级视图实现列表视图

views.py:

# 三级视图实现列表视图
class BookListThirdView(ListAPIView, CreateAPIView):
    # 提供公共的属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

子路由:

url(r'^third_view_books/$', views.BookListThirdView.as_view()),

运行结果:
在这里插入图片描述
在这里插入图片描述

2.三级视图实现详情视图

views.py:

# 三级视图实现详情视图
class BookDetailThirdView(RetrieveAPIView, UpdateAPIView, DestroyAPIView):
    # 提供通用的属性
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer
    lookup_field = 'id'

子路由:

url(r'^third_view_books/(?P<id>\d+)/$', views.BookDetailThirdView.as_view())

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四.ViewSets(视图集)

DRF的ViewSets官网:https://www.django-rest-framework.org/api-guide/viewsets/
视图集特点:
  1.可以将一组相关的操作,放在一个类中进行完成
  2.不提供get,post方法,使用retrieve,create方法来替代
  3.可以将标准的请求方式(get,post,put,delete),和mixin中方法做映射
常见的视图集:

类名称父类作用
ViewSetAPIView,ViewSetMixin可以做路由映射
GenericViewSetGenericAPIView, ViewSetMixin可以做路由映射,可以使用三个属性,三个方法
ModelViewSetGenericAPIView,5个mixin类所有的增删改查功能,可以使用三个属性,三个方法
ReadOnlyModelViewSetGenericAPIView,RetrieveModelMixin,ListModelMixin获取单个,所有数据,可以使用三个属性,三个方法

当我们想在一个类中获取所有对象和单个对象时,我们又不能在一个类中写两个get方法,所以我们可以使用视图集来实现

1.ViewSet

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

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

# 使用viewset实现获取所有和单个
class BooksViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing or retrieving books.
    """
    def list(self, request):
        queryset = BookInfo.objects.all()
        serializer = BookInfoModelSerializer(instance=queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = BookInfo.objects.all()
        book = get_object_or_404(queryset, pk=pk)
        serializer = BookInfoModelSerializer(instance=book)
        return Response(serializer.data)

设置路由:

url(r'^viewset/$', views.BooksViewSet.as_view({'get': 'list'})),
url(r'^viewset/(?P<pk>\d+)/$', views.BooksViewSet.as_view({'get': 'retrieve'})),

运行结果:
在这里插入图片描述
在这里插入图片描述

2.ReadOnlyModelViewSet

继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。
views.py:

# 使用ReadOnlyModelViewSet实现获取单个和所有
class BooksReadOnlyModelViewSet(ReadOnlyModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

设置路由:

url(r'^readonly_viewset/$', views.BooksReadOnlyModelViewSet.as_view({'get': 'list'})),
url(r'^readonly_viewset/(?P<pk>\d+)/$', views.BooksReadOnlyModelViewSet.as_view({'get': 'retrieve'})),

运行结果:
在这里插入图片描述
在这里插入图片描述

3.ModelViewSet

继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
views.py:

# ModelViewSet实现列表视图,详情视图功能
class BookModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

设置路由:

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

运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.视图集额外动作

(1)基本使用
在视图集中,除了上述默认的方法动作外,还可以添加自定义动作。

view.py:

class BookModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer  

    # 需求:获取阅读量大于111的书籍
    def bread_book(self, request):
        # 获取指定书籍
        books = BookInfo.objects.filter(bread__gt=111)
        # 创建序列化器对象
        serializer = self.get_serializer(instance=books, many=True)
        # 返回响应
        return Response(serializer.data)

写在视图集里面的内容,都是做路由映射的
子路由:

url(r'^books/bread/$', views.BookModelViewSet.as_view({'get': 'bread_book'})),

运行结果:
在这里插入图片描述
(2)partial
可以编写额外动作添加参数,并且更新局部信息
views.py:

class BookModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # 需求:修改书籍编号为11的,阅读量为222
    def update_book_bread(self, request, pk):
        # 获取参数
        book = self.get_object()
        data = request.data
        # 创建序列化器对象
        serializer = self.get_serializer(instance=book, data=data, partial=True)
        # 校验,入库
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 返回响应
        return Response(serializer.data, status=201)

子路由:

url(r'^books/bread/(?P<pk>\d+)/$', views.BookModelViewSet.as_view({'put': 'update_book_bread'})),

运行结果:
在这里插入图片描述

五.Router(路由)

对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。
REST framework提供了两个router:SimpleRouter和DefaultRouter
views.py:

class BookModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer

    # 需求:修改书籍编号为11的,阅读量为222
    def update_book_bread(self, request, pk):
        # 获取参数
        book = self.get_object()
        data = request.data
        # 创建序列化器对象
        serializer = self.get_serializer(instance=book, data=data, partial=True)
        # 校验,入库
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 返回响应
        return Response(serializer.data, status=201)

1.DefaultRouter

子路由:

from . import views
from rest_framework.routers import DefaultRouter

urlpatterns = [
]

# 创建路由对象
router = DefaultRouter()
# 注册视图表
router.register('books', views.BookModelViewSet, basename='test')
urlpatterns += router.urls
# 输出结果:
print(urlpatterns)

说明:
 register(prefix, viewset, base_name)
   prefix:该视图集的路由前缀
   viewset:视图集
   base_name:路由名称的前缀

运行结果:

# 列表路由及其json形式
[<RegexURLPattern test-list ^books/$>, 
<RegexURLPattern test-list ^books\.(?P<format>[a-z0-9]+)/?$>, 
# 详情路由及其json形式
<RegexURLPattern test-detail ^books/(?P<pk>[^/.]+)/$>, 
<RegexURLPattern test-detail ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>, 
# 根路由及其json形式
<RegexURLPattern api-root ^$>, 
<RegexURLPattern api-root ^\.(?P<format>[a-z0-9]+)/?$>]

由上可知,Routers能够帮助我们快速实现路由信息

部分截图:
列表路由:在这里插入图片描述

列表路由json形式:

在这里插入图片描述

详情路由:
在这里插入图片描述
在这里插入图片描述
详情路由json形式
在这里插入图片描述
根路由:
在这里插入图片描述
在这里插入图片描述

注意点:
  在网页上访问时,需要在settings中注册rest_framework
  使用DRF可以自动根据前端需要的类型,返回对应格式的数据

2.SimpleRouter

子路由:

from . import views
from rest_framework.routers import SimpleRouter

urlpatterns = [
]

# 创建路由对象
router = SimpleRouter()
# 注册视图表
router.register('books', views.BookModelViewSet, basename='test')
urlpatterns += router.urls
# 输出结果:
print(urlpatterns)

运行结果:

[<RegexURLPattern test-list ^books/$>, 
<RegexURLPattern test-detail ^books/(?P<pk>[^/.]+)/$>]

在这里插入图片描述

3.视图集包含action装饰器

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

action装饰器可以接收两个参数:
   methods: 该action支持的请求方式,列表传递
   detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
     True:表示使用通过URL获取的主键对应的数据对象
     False:表示不使用URL获取主键
views.py:

class BookModelViewSet(ModelViewSet):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoModelSerializer
    # 需求:获取阅读量大于111的书籍
    @action(methods=['get'], detail=False) # 生成路由规则:前缀/方法名
    def bread_book(self, request):
        # 获取指定书籍
        books = BookInfo.objects.filter(bread__gt=111)
        # 创建序列化器对象
        serializer = self.get_serializer(instance=books, many=True)
        # 返回响应
        return Response(serializer.data)
    # 需求:修改书籍编号为13的,阅读量为222
    @action(methods=['put'], detail=True) # 生成路由规则:前缀/{pk}/方法名/
    def update_book_bread(self, request, pk): 
        # 获取参数
        book = self.get_object()
        data = request.data
        # 创建序列化器对象
        serializer = self.get_serializer(instance=book, data=data, partial=True)
        # 校验,入库
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 返回响应
        return Response(serializer.data, status=status.HTTP_201_CREATED)

子路由:

from . import views
from rest_framework.routers import SimpleRouter
urlpatterns = [
]

# 创建路由对象
router = SimpleRouter()
# 注册视图表
router.register('books', views.BookModelViewSet, basename='test')
urlpatterns += router.urls
# 输出结果:
print(urlpatterns)

运行结果:

[<RegexURLPattern test-list ^books/$>, 
<RegexURLPattern test-bread-book ^books/bread_book/$>, 

<RegexURLPattern test-detail ^books/(?P<pk>[^/.]+)/$>, 
<RegexURLPattern test-update-book-bread ^books/(?P<pk>[^/.]+)/update_book_bread/$>]

截图:
在这里插入图片描述
在这里插入图片描述

4.路由router形成url的方式

1)SimpleRouter
在这里插入图片描述

2)DefaultRouter
在这里插入图片描述

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

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值