Django-restframework 视图类

HTTP请求响应

drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作。所以在Django原有的django.views.View类基础上,drf封装了多个视图子类供我们使用。
Django-restframework提供的视图的主要作用:

  • 控制序列化器的执行(检验、保存、转换数据)
  • 控制数据库查询的执行
  • 调用请求类和相应类

请求与响应

内容协商:drf在django原有的基础上,新增了一个request对象继承到了APIView视图类,并在django原有的HttpResponse响应类的基础上实现了一个子类rest_framework.response.Response响应类。这两个类,都是基于内容协商来完成数据的格式转换的。

request --> parser --> 识别客户端请求头中的Content-Type来完成数据转换 --> 类字典
response --> render --> 识别客户端请求头的Accept来提取客户端期望的返回数据格式 --> 转换成客户端期望格式数据

request

常用属性

.data

request.data返回解析之后的请求体数据。类似于Django中标准的request.POST和request.FILES属性,但提供如下特征:

  • 包含了解析之后的文件和非文件数据
  • 包含了对 POST、PUT、PATCH 请求方式解析后的数据
  • 利用了restframework的parsers解析器,不但支持表单类型数据,也支持json格式数据
.query_params

request.query_params与Django标准的request.GET相同,只是更换了更正确的名称而已。

._request

request._request获取django封装的Request对象。

response

视图

Django-restframework提供的视图的主要作用:

  • 控制序列化器的执行(检验、保存、转换数据)
  • 控制数据库模型的操作

普通视图

RestFramework提供了众多的通用视图基类与扩展类,以便简化视图的编写。

2个视图基类

APIView基本视图类

rest_framework.views.APIView

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

APIView与View的不同之处在于:

  • 传入到视图方法中的是RestFramework的request对象,而不是Django的HttpRequest对象。
  • 视图方法可以返回RestFramework的Response对象,视图会为影响数据设置(render)符号前端期望要求的格式。
  • 任何APIException异常都会被捕获到,并且处理成合适格式的响应信息返回给客户端。
  • 重新声明了一个新的as_view方法并在dispatch()进行路由分发前,会对请求的客户端进行身份认证、权限检查、流量控制。
    序列化器:
from rest_framework import serializers
from students.models import Student


class StudentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = "__all__"

编写视图类:

from rest_framework import request, status
from rest_framework.response import Response
from rest_framework.views import APIView
from students.models import Student
from .serializers import StudentModelSerializer


class StudentAPIView(APIView):
    def get(self, request):
        """
        获取所有学生信息
        /demo/students/
        """
        student_list = Student.objects.all()
        serializer = StudentModelSerializer(instance=student_list, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request):
        """
        添加一个学生信息
        """
        # 1.获取客户端提交的数据
        data = request.data
        # 2.实例化序列化器,获取序列化对象
        serializer = StudentModelSerializer(data=data)
        # 3.反序列化【验证数据、保存数据到数据库中】
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class StudentInfoAPIView(APIView):
    def get(self, request, pk):
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        serializer = StudentModelSerializer(instance=student)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk):
        # 1. 使用pk作为条件获取模型对象
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # 2. 获取客户端提交的数据
        serializer = StudentModelSerializer(instance=student, data=request.data)

        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request, pk):
        try:
            Student.objects.get(pk=pk).delete()
        except Student.DoesNotExist:
            pass

        return Response(status=status.HTTP_204_NO_CONTENT)

定义路由:

from django.urls import path, re_path
from . import views

urlpatterns = [
    path('students/', views.StudentAPIView.as_view()),
    re_path("students/(?P<pk>\d+)/", views.StudentInfoAPIView.as_view())
]

GenericAPIView视图子类

通用视图类主要作用就是把视图中的独特代码抽离出来,让视图方法中的代码更加通用,方便把通用代码进行简写。

rest_framework.generics.GenericAPIView

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

它有两个属性:

  • serializer_class 知名视图使用的序列化器
  • queryset 指明使用的数据查询集

它有四个常用的方法:

  • get_serializer_class(self) 当出现一个视图类中调用多个序列化器时,那么可以通过条件判断在get_serializer_class方法中通过不同的序列化器类名就可以让视图方法执行不同的序列化器对象了。
  • get_serializer(self, args, *kwargs) 返回序列化器对象,主要用来提供给Mixin扩展类使用,如果我们在视图中想要获取序列化器对象,也可以直接调用此方法。
  • get_queryset(self) 返回视图使用的查询集,主要用来提供给Mixin扩展类使用,是列表视图与详情视图获取数据的基础,默认返回querysert属性,可以重写。
  • get_object(self) 返回详情视图所需的模型类数据对象,主要用来提供给Mixin扩展类使用。

编写视图类:

"""GenericAPIView通用视图类"""
from rest_framework.generics import GenericAPIView


class StudentGenericAPIView(GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    def get(self, request):
        students_list = self.get_queryset()
        serializer = self.get_serializer(instance=students_list, 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)


class StudentInfoGenericAPIView(GenericAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    def get(self, request, pk):
        student = self.get_object()
        serializer = self.get_serializer(instance=student)
        return Response(serializer.data)

    def put(self, request, pk):
        student = self.get_object()
        serializer = self.get_serializer(instance=student, data=request.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)

5个视图扩展类

ListModelMixin

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

CreateModelMixin

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

RetrieveModelMixin

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

UpdateModelMixin

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

DestroyModelMixin

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

"""使用drf内置的模型扩展类结合GenericAPIView实现视图方法的简写操作"""
from rest_framework.mixins import ListModelMixin
from rest_framework.mixins import CreateModelMixin
from rest_framework.mixins import RetrieveModelMixin
from rest_framework.mixins import UpdateModelMixin
from rest_framework.mixins import DestroyModelMixin


class StudentMixinView(GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

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

    def post(self, request):
        return self.create(request)
class StudentInfoMixinView(GenericAPIView, RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

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

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

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

9个视图子类

CreateAPIView

ListAPIView

RetrieveAPIView

DestroyAPIView

UpdateAPIView

ListCreateAPIView

RetrieveUpdateAPIView

RetrieveDestroyAPIView

RetrieveUpdateDestroyAPIView

from rest_framework.generics import ListAPIView, CreateAPIView, RetrieveUpdateDestroyAPIView


class StudentView(ListAPIView, CreateAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

class StudentInfoView(RetrieveUpdateDestroyAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

视图集ViewSet

使用视图集ViewSet,可以将一系列试图相关的代码逻辑和相关的http请求动作封装到一个类中:

  • list()提供一组数据
  • retrieve()提供单个数据
  • create()创建数据
  • update()修改数据
  • destory()删除数据
    ViewSet视图集类不再限制视图方法名只允许get()、post()等这种情况了,而是允许开发者根据自己的需要定义自定义方法名,例如list()、create()等,然后经过路由中使用http和这些视图方法名进行绑定调用。
    视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。

ViewSet

from rest_framework.viewsets import ViewSet, GenericViewSet


class StudentViewSet(ViewSet):
    def get_list(self, request):
        student_list = Student.objects.all()
        serializer = StudentModelSerializer(instance=student_list, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

路由

urlpatterns = [
    # 视图集ViewSet
    path('students5/', views.StudentViewSet.as_view({'get': 'get_list'})),
]

GenericViewSet

class StudentGenericViewSet(GenericViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

    def list(self, request):
        student_list = self.get_queryset()
        serializer = self.get_serializer(instance=student_list, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def create(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status.HTTP_201_CREATED)

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

    def update(self, request, pk):
        instance = self.get_object()
        serializer = self.get_serializer(instance=instance, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

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

GenericViewSet + Mixin

""" GenericViewSet通用视图集 + 混入类"""


class StudentMixinViewSet(GenericViewSet, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin,
                          DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer


"""
    上面的接口类继承的父类太多了,可以继续让一些合并的视图集父类让视图继承即可
"""
from rest_framework.viewsets import ReadOnlyModelViewSet, ModelViewSet


class StudentMixinViewSet2(ReadOnlyModelViewSet, CreateModelMixin, UpdateModelMixin, DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer


class StudentMixinViewSet3(ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
posted @ 2023-01-05 16:53  Gazikel  阅读(61)  评论(0编辑  收藏  举报