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)