在Django REST Framework中,视图类是处理请求的核心组件。可以通过多种方式定义视图,包括视图基类、Mixin扩展类和子类视图。
使用视图基类时,需要继承一个或多个基类,并实现相应的方法。例如,如果继承了 APIView,需要实现 get()、post()、put()、delete() 等方法。
1. APIView:用于处理任何类型的HTTP请求,并自定义响应行为。
2. GenericAPIView:与 APIView 类似,但具有一些内置的通用方法,例如对象查询和序列化处理。
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是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\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继承自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\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)
使用GenericAPIView,其中代码和视图所使用的序列化器类和查询集已经没有直接关系,DRF其实已经做了封装,就是5个Mixin扩展类。
列表视图扩展类,提供
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)
创建视图扩展类,提供
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)
详情视图扩展类,提供
retrieve(request, *args, **kwargs)
方法,可以快速实现返回一个存在的数据对象。如果存在,返回200, 否则返回404。
re_path(r'^test/(?P\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)
更新视图扩展类,提供
update(request, *args, **kwargs)
方法,可以快速实现更新一个存在的数据对象。成功返回200,序列化器校验数据失败时,返回400错误。
re_path(r'^test/(?P\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)
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.
删除视图扩展类,提供
destroy(request, *args, **kwargs)
方法,可以快速实现删除一个存在的数据对象。成功返回204,不存在返回404。
re_path(r'^test/(?P\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继承自: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继承自: GenericAPIView、CreateModelMixin,提供 post 方法
RetrieveAPIView继承自: GenericAPIView、RetrieveModelMixin,提供 get 方法
re_path(r'^test/(?P\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继承自:GenericAPIView、DestoryModelMixin,提供 delete 方法
UpdateAPIView继承自:GenericAPIView、UpdateModelMixin,提供 put 和 patch 方法
ListCreateAPIView继承自:GenericAPIView、ListModelMixin、CreateModelMixin,提供 get 和 post 方法
RetrieveUpdateAPIView继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin,提供 get、put、patch方法
RetrieveDestroyAPIView继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin,提供 get 和 delete 方法
RetrieveUpdateDestoryAPIView继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin,提供 get、put、patch、delete方法