Django REST Framework(DRF)框架之视图类(视图基类、Mixin扩展类、子类视图)

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Django REST Framework(DRF)框架之视图类(视图基类、Mixin扩展类、子类视图),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

视图类概述

在Django REST Framework中,视图类是处理请求的核心组件。可以通过多种方式定义视图,包括视图基类、Mixin扩展类和子类视图。

视图基类

使用视图基类时,需要继承一个或多个基类,并实现相应的方法。例如,如果继承了 APIView,需要实现 get()、post()、put()、delete() 等方法。

1. APIView:用于处理任何类型的HTTP请求,并自定义响应行为。
2. GenericAPIView:与 APIView 类似,但具有一些内置的通用方法,例如对象查询和序列化处理。

Mixin扩展类

Mixin是一种用于解决类之间代码重用的设计模式。在 DRF中,Mixin类是用于扩展视图功能的辅助类。

Mixin扩展类通常与视图基类一起使用。例如,编写一个 AuthenticationMixin类来添加身份验证功能,然后将其与 APIView基类一起使用。

1. ListModelMixin:实现获取资源列表的逻辑
2. CreateModelMixin:实现创建数据资源的逻辑
3. RetrieveModelMixin:实现获取单个资源的逻辑
4. UpdateModelMixin:实现更新现有数据资源的逻辑
5. DestoryModelMixin:实现删除数据资源的逻辑

子类视图类

子类视图是DRF 中最高级别的视图类型。它们是基于已经定义的视图和Mixin来创建的,具有更优雅的代码结构。可以通过继承一个或多个Mixin和一个视图基类来创建子类视图。

使用子类视图时,只需要实现所需的方法即可。例如,如果继承了ListAPIView 类,只需要实现 get_queryset() 方法即可。

1. ListAPIView:获取数据列表的视图类
2. CreateAPIView:创建新数据资源的视图类
3. RetrieveAPIView:获取单个资源的视图类
4. UpdateAPIView:更新现有数据资源的视图类
5. DestroyAPIView:删除数据资源的视图类
6. ListCreateAPIView:结合ListAPIView 和 CreateAPIView 的视图类,用于同时获取和创建数据资源。
7. RetreiveUpdateAPIView:结合RetrieveAPIView 和 UpdateAPIView 的视图类,用于同时获取和更新单个数据资源。
8. RetrieveDestroyAPIView:结合RetrieveAPIView 和 DestroyAPIView 的视图类,用于同时获取和删除单个数据资源。
9. RetrieveUpdateDestroyAPIView:结合RetrieveAPIView、UpdateAPIView 和 DestroyAPIView 的视图类,用于同时获取、更新和删除单个数据资源。

视图基类

APIView

APIView是REST framework提供的所有视图的基类,继承自Django的View类。

APIView与View的不同之处在于:

传入到视图中的request对象是REST framework的Request对象,而不是Django原始的HttpRequest对象

视图可以直接返回REST framework的Response对象,响应数据会根据客户端请求头Accpet自动转换为对应的格式进行返回

任何APIException异常都会被捕获到,并且处理成合适的响应信息返回给客户端

在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制

1.Request对象

视图继承APIView之后,传入视图的request对象是DRF框架提供的Request类的对象,Request类的对象有两个属性:

属性名 说明
data 包含解析之后的请求体数据,已经解析为了字典或类字典,相当于Django原始request对象的body、POST、FILES属性
query_params 包含解析之后的查询字符串数据,相当于Django原始request对象的GET属性

2.Response对象

视图继承APIView之后,响应时可以统一返回Response对象

原始的响应数据,会根据客户端请求头的Accpet,自动转换为对应的格式并进行返回

Accept请求头 说明
application/json 服务器会将原始响应数据转换为json数据进行返回,没指定Accept时,默认返回json
text/html 服务器会将原始响应数据转换为html网页进行返回;

3.APIView的使用

re_path(r'^test/$', views.TestView.as_view(), name='test'),
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.users.models import User
from apps.users.serializers import UserSerializer

class TestView(APIView):

    def get(self, request):
        queryset = User.objects.all()
        # 序列化
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def post(self, request):
        # 反序列化-数据校验
        serializer = UserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 反序列化-数据保存
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view(), name='test'),
class TestView(APIView):

    def get(self, request, pk):
        try:
            user = User.objects.get(id=pk)
        except User.DoesNotExist:
            raise Http404

        # 数据进行序列化
        serializer = UserSerializer(user)
        print(serializer.data)
        return Response(serializer.data)

    def put(self, request, pk):
        try:
            user = User.objects.get(id=pk)
        except User.DoesNotExist:
            raise Http404

        # 反序列化-数据校验
        serializer = UserSerializer(user, data=request.data)
        serializer.is_valid(raise_exception=True)
        # 反序列化-数据保存
        serializer.save()
        return Response(serializer.data)

    def delete(self, request, pk):
        try:
            user = User.objects.get(id=pk)
        except User.DoesNotExist:
            raise Http404

        user.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

GenericAPIView

GenericAPIView继承自APIVIew,在APIView功能基础上,增加了操作序列化器和数据库查询的方法,作用是为Mixin扩展类的执行提供方法支持。通常在使用时,可搭配一个或多个Mixin扩展类。

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

属性:

serializer_class:指明视图使用的序列化器

方法:

get_serializer_class(self) : 返回序列化器类,默认返回serializer_class,可以重写

get_serializer(self, args, **kwargs) : 返回创建序列化器类的对象,如果我们在视图中想要创建序列化器对象,可以直接调用此方法

2.提供的关于数据库查询的属性与方法

属性:

queryset:指明使用的数据查询集

方法:

get_queryset(self):返回视图使用的查询集,默认返回queryset属性,可以重写

get_object(self):返回从视图使用的查询集中查询指定的对象(默认根据pk进行查询),如查询不到,此方法会抛出Http404异常

3.其他可以设置的属性

pagination_class:指明分页控制类

filter_backends:指明过滤控制后端

GenericAPIView的使用

re_path(r'^test/$', views.TestView.as_view(), name='test'),
class TestView(GenericAPIView):
    # 指定视图所使用的序列化器类
    serializer_class = UserSerializer
    # 指定视图所使用的查询集
    queryset = User.objects.all()

    def get(self, request):
        queryset = self.get_queryset()

        # 序列化
        serializer = self.get_serializer(queryset, many=True)

        return Response(serializer.data)

    def post(self, request):
        # 反序列化-数据校验
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        # 反序列化-数据保存
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)
re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view(), name='test'),
class TestView(GenericAPIView):
    # 指定视图所使用的序列化器类
    serializer_class = UserSerializer
    # 指定视图所使用的查询集
    queryset = User.objects.all()

    def get(self, request, pk):
        instance = self.get_object()
        serializer = UserSerializer(instance)
        return Response(serializer.data)

    def put(self, request, pk):
        instance = self.get_object()
        # 反序列化-数据校验
        serializer = UserSerializer(instance, data=request.data)
        serializer.is_valid(raise_exception=True)
        # 反序列化-数据保存
        serializer.save()
        return Response(serializer.data)

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

Mixin扩展类

使用GenericAPIView,其中代码和视图所使用的序列化器类和查询集已经没有直接关系,DRF其实已经做了封装,就是5个Mixin扩展类。

ListModelMixin

列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。该Mixin的list方法会对数据进行过滤和分页。

class TestView(ListModelMixin, GenericAPIView):
	serializer_class = UserSerializer
    queryset = User.objects.all()

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

CreateModelMixin

创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。如果序列化器对前端发送的数据验证失败,返回400错误。

class TestView(CreateModelMixin, GenericAPIView):
	serializer_class = UserSerializer
    queryset = User.objects.all()

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

在这里插入图片描述

RetrieveModelMixin

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

 re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view(), name='test'),
class TestView(RetrieveModelMixin, GenericAPIView):
	serializer_class = UserSerializer
    queryset = User.objects.all()

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

UpdateModelMixin

更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。成功返回200,序列化器校验数据失败时,返回400错误。

re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view(), name='test'),
class TestView(UpdateModelMixin, GenericAPIView):
	serializer_class = UserSerializer
    queryset = User.objects.all()

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

在这里插入图片描述
注意:当遇到以下异常时,需要在URL末尾添加/

RuntimeError: You called this URL via PUT, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining PUT data. Change your form to point to 127.0.0.1:8000/test/3/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.

DestroyModelMixin

删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。

re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view(), name='test'),
class TestView(DestroyModelMixin, GenericAPIView):
	serializer_class = UserSerializer
    queryset = User.objects.all()

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

子类视图

Django框架为了方便视图的编写,还提供了9个子类视图类,子类视图类同时继承了GenericAPIView和对应的Mixin扩展类,而且还提供了对应的请求处理方法。

ListAPIView

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

re_path(r'^test/$', views.TestView.as_view(), name='test'),
class TestView(ListCreateAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.all()

Get http://127.0.0.1:8000/test/

CreateAPIView

CreateAPIView继承自: GenericAPIView、CreateModelMixin,提供 post 方法

RetrieveAPIView

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

re_path(r'^test/(?P<pk>\d+)/$', views.TestView.as_view(), name='test'),
class TestView(RetrieveAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.all()

Get http://127.0.0.1:8000/test/1/

DestoryAPIView

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

UpdateAPIView

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

ListCreateAPIView

ListCreateAPIView继承自:GenericAPIView、ListModelMixin、CreateModelMixin,提供 get 和 post 方法

RetrieveUpdateAPIView

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

RetrieveDestroyAPIView

RetrieveDestroyAPIView继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin,提供 get 和 delete 方法

RetrieveUpdateDestoryAPIView

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136836.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!