Django REST framework学习笔记(5)-视图类

DRF除了在数据序列化部分简写了代码,还在视图提供了简写操作,在doango.views.View类基础上,封装了多个视图子类,提供我们使用。

DRF提供的视图主要作用:

  • 控制序列化器的执行(校验,保存,转换数据)
  • 控制数据库查询的执行
  • 调用请求类和响应类,(这两个类也是drf扩展了一些功能的类)
Django REST framework学习笔记(5)-视图类

2个视图基类

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

APIView

REST framework提供了一个APIView类(基本视图类),它继承于Django的View类。

APIView类与不同的View类有所不同:

  • 传递给处理方法的request对象是REST framework的Request实例,而不是Django的HttpRequest实例。
  • 处理方法可能返回REST framework的Response,而不是Django的HttpResponse 。该视图将管理内容协商,并在响应中设置正确的渲染器。
  • 任何APIException异常都会被捕获并进行适当的响应。
  • 传入的请求会进行认证,在请求分派给处理方法之前将进行适当的权限检查(允许或限制)。

像往常一样,使用 APIView 类与使用常规 View 类非常相似,传入的请求被分派到适当的处理方法,如 .get().post()。此外还新增了类属性

API 策略属性(policy attributes)

  • .renderer_classes:设置渲染器
  • .parser_classes:设置解析器
  • .authentication_classes:身份认证类
  • .throttle_classes:流量控制类
  • .permission_classes:权限检查类
  • .content_negotiation_class
 #1.models.py
 class Student(models.Model):
     name = models.CharField(max_length=100, verbose_name='姓名')
     sex = models.BooleanField(default=1, verbose_name='性别')
     classmate = models.CharField(max_length=20, verbose_name='班级')
     desc = models.TextField(verbose_name='个性签名')
 
     def __str__(self):
         return self.name
 
 #2.serializer.py
 from rest_framework import serializers
 from . import models
 
 class StuModelSer(serializers.ModelSerializer):
     class Meta:
         model = models.Student
         fields = "__all__"
 
 #3.views.py
 from rest_framework.views import APIView
 from rest_framework.response import Response
 from rest_framework import status
 from . import models
 from .serializer import StuModelSer
 
 class StuApiView(APIView):
     """获取所有数据和修改数据 的接口"""
     def get(self, request):
         # 1.从数据库中查询数据
         stu_list = models.Student.objects.all()
         # 2.序列化数据,获取序列化对象
         ser = StuModelSer(instance=stu_list, many=True)
         # 3.返回数据给客户端
         return Response(ser.data, status=status.HTTP_200_OK)
 
     def post(self, request):
         # 1.序列化,获取到的数据
         ser = StuModelSer(data=request.data)
         if ser.is_valid():  # 2.验证数据
             ser.save()  # 3.保存数据
             return Response(ser.data, status=status.HTTP_201_CREATED)
         return Response({"message": ser.errors}, status=status.HTTP_400_BAD_REQUEST)
 
 
 class StuApiViews(APIView):
 """获取1个和修改,删除的接口"""
     def get(self, request, pk):
         # 1.从数据库中查询数据
         try:
             student = models.Student.objects.get(pk=pk)
         except models.Student.DoesNotExist:
             return Response({"message": "数据不存在"}, status=status.HTTP_404_NOT_FOUND)
         # 2.序列化数据,获取序列化对象
         serializer = StuModelSer(instance=student)
         # 3.返回数据给客户端
         return Response(serializer.data, status=status.HTTP_200_OK)
 
     def put(self, request, pk):
         # 1.从数据库中查询数据
         try:
             student = models.Student.objects.get(pk=pk)
         except models.Student.DoesNotExist:
             return Response({"message": "数据不存在"}, status=status.HTTP_404_NOT_FOUND)
         # 2.序列化提交进来数据
         serializer = StuModelSer(instance=student, data=request.data)
         # 3. 验证数据和保存
         serializer.is_valid(raise_exception=True)
         serializer.save()
         # 4.返回数据给客户端
         return Response(serializer.data, status=status.HTTP_200_OK)
 
     def delete(self, request, pk):
         try:
             models.Student.objects.get(pk=pk).delete()
         except models.Student.DoesNotExist:
             return Response({"message": "数据不存在"}, status=status.HTTP_404_NOT_FOUND)
         return Response({"message": "ok"}, status=status.HTTP_204_NO_CONTENT)
 
 #4.urls.py
 from django.urls import path, re_path
 from rest_framework.routers import DefaultRouter
 from . import views
 
 urlpatterns = [
     path('stu/', views.StuApiView.as_view()),
     re_path(r'^stu/(?P\d+)/#39;, views.StuApiViews.as_view()),
 ]

GenericAPIView

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

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

常用属性

  • serializer_class用于验证和反序列化输入、序列化输出的序列化类。必须设置此属性,或覆盖get_serializer_class()方法
  • queryset用于从此视图返回对象的查询集。必须设置此属性,或覆盖get_queryset()方法。如果你重写了一个视图方法,在视图方法中,你应该调用get_queryset()而不是直接访问这个属性,这一点很重要!因为REST 会在内部对queryset的结果进行缓存用于后续所有请求。
  • lookup_field用于执行各个模型实例的对象查找的模型字段。默认为 'pk'
  • lookup_url_kwarg 用于对象查找的URL关键字参数。URL conf应该包含与此值相对应的关键字参数。如果未设置,则默认使用与 lookup_field 相同的值。

基本方法

  • get_serializer_class(self)返回用于序列化的类。默认返回serializer_class属性。
继承了APIView当出现一个视图类中调用多个序列化器时,
可以通过条件判断在get_serializer_class方法中通过返回不同的序列化器类名,
就可以让视图执行不同的序列化器对象。

class StuGenericAPIView(GenericAPIView):
     def get_serializer_class(self):  #视图中使用多个序列化器
         if self.request.method.lower() == "put":
             return StuModelSer
         else:
             return StuSer
  
 #上面是使用2个序列化器,这个是,只使用一个序列化器
     # serializer_class = StuModelSer
  • get_queryset(self)应该返回列表视图的查询集,并应该将其用作查看详细视图的基础。默认返回由queryset属性指定的查询集。
def get_queryset(self):
     user = self.request.user
     return user.accounts.all()
 
 #重写视图类中的各种方法时。
 class UserList(generics.ListCreateAPIView):
     queryset = User.objects.all()
     serializer_class = UserSerializer
     permission_classes = (IsAdminUser,)
 
     def list(self, request):
         # 注意使用`get_queryset()`而不是`self.queryset`
         queryset = self.get_queryset()
         serializer = UserSerializer(queryset, many=True)
         return Response(serializer.data)
  • get_object(self)应该返回详细视图的对象实例。默认使用lookup_field参数来过滤基本查询集
 def get_object(self):
     queryset = self.get_queryset()
     filter = {}
     for field in self.multiple_lookup_fields:
         filter[field] = self.kwargs[field]
 
     obj = get_object_or_404(queryset, **filter)
     self.check_object_permissions(self.request, obj)
     return obj
 """通用视图类"""

#model.py和serializer.py的内容跟APIview一样
 
 #3.views.py
 from rest_framework.generics import GenericAPIView
 
 class StuGenericAPIView(GenericAPIView):
     queryset = models.Student.objects.all()
     serializer_class = StuModelSer
 
     def get(self, request):  # 获取所有数据
         # 1.从数据库中查询数据
         queryset = self.get_queryset()
         # 2.序列化数据
         serializer = self.get_serializer(instance=queryset, many=True)
         # 3.返回数据给客户端
         return Response(serializer.data, status=status.HTTP_200_OK)
 
     def post(self, request):  # 添加一条数据
         # 1.获取客户端提交的数据,实例化序列化器
         serializer = self.get_serializer(data=request.data)
         # 2.反序列化,保存数据到数据库
         serializer.is_valid(raise_exception=True)
         serializer.save()
         # 3.把新增的数据返回给客户端
         return Response(serializer.data, status=status.HTTP_201_CREATED)
 
 class StuGenericAPIViews(GenericAPIView):
     queryset = models.Student.objects.all()
     serializer_class = StuModelSer
 
     def get(self, request, pk):  # 获取一条数据
         # 1.从数据库中查询数据
         instance = self.get_object()
         # 2.序列化数据
         serializer = self.get_serializer(instance=instance)
         # 3.返回数据给客户端
         return Response(serializer.data, status=status.HTTP_200_OK)
 
     def put(self, request, pk):  # 更新一条数据
         # 1.从数据库中查询数据
         instance = self.get_object()
         # 2.序列化提交进来数据
         serializer = self.get_serializer(instance=instance, data=request.data)
         # 3. 验证数据和保存
         serializer.is_valid(raise_exception=True)
         serializer.save()
         # 4.返回数据给客户端
         return Response(serializer.data, status=status.HTTP_200_OK)
 
     def delete(self, request, pk):  # 删除一条数据
         # 1.根据pk值获取要删除的数据
         self.get_object().delete()
         # 2.返回结果
         return Response({"message": "ok"}, status=status.HTTP_204_NO_CONTENT)
 
 #4.urls.py,新增genericAPIView视图
 urlpatterns = [
     # APIView
     path('stu/', views.StuApiView.as_view()),
     re_path(r'^stu/(?P\d+)/#39;, views.StuApiViews.as_view()),
 
     # GenericAPIView
     path('gstu/', views.StuGenericAPIView.as_view()),
     re_path(r'^gstu/(?P\d+)/#39;, views.StuGenericAPIViews.as_view()),
 ]

5个视图扩展类

结合GenericAPIView实现通用视图方法的简写操作,

ListModelMixin

提供一个 .list(request, *args, **kwargs) 方法,实现了列出一个查询集。如果查询集已填充,则返回 200 OK 响应,并将 queryset 的序列化表示形式作为响应的主体。响应数据可以设置分页。

CreateModelMixin

提供 .create(request, *args, **kwargs) 方法,实现创建和保存新模型实例。如果创建了一个对象,则会返回一个 201 Created 响应,并将该对象的序列化表示形式作为响应的主体。如果表示包含名为 url 的键,则响应的 Location header 将填充该值。如果为创建对象提供的请求数据无效,则将返回 400 Bad Request 响应,并将错误细节作为响应的主体。

RetrieveModelMixin

提供 .retrieve(request, *args, **kwargs) 方法,该方法实现在响应中返回现有的模型实例。如果可以获取对象,则返回 200 OK 响应,并将对象的序列化表示作为响应的主体。否则,将返回一个 404 Not Found

UpdateModelMixin

提供 .update(request, *args, **kwargs) 方法,实现更新和保存现有模型实例

还提供了一个 .partial_update(request, *args, **kwargs) 方法,它与更新方法类似,只是更新的所有字段都是可选的。这允许支持 HTTP PATCH 请求。

如果成功更新对象,则返回 200 OK 响应,并将对象的序列化表示形式作为响应的主体。如果提供的用于更新对象的请求数据无效,则将返回 400 Bad Request 响应,并将错误细节作为响应的主体。

DestroyModelMixin

提供一个 .destroy(request, *args, **kwargs) 方法,实现现有模型实例的删除。如果一个对象被删除,则返回一个 204 No Content ,否则它将返回一个 404 Not Found

使用示例

 #model.py和serializer.py的内容跟APIview一样
 
 #1.views.py
 from rest_framework.mixins import (
     ListModelMixin,  # 获取多条数据,list
     CreateModelMixin,  # 添加一条数据,create
     RetrieveModelMixin,  # 获取一条数据 retrieve
     UpdateModelMixin,  # 更新一条数据 update
     DestroyModelMixin  # 删除一条数据 destroy
 )
 
 class StuMixinView(GenericAPIView, ListModelMixin, CreateModelMixin):
     queryset = models.Student.objects.all()
     serializer_class = StuModelSer
 
     def get(self, request):  # 查询所有数据
         return self.list(request)
 
     def post(self, request):  # 新增一条数据
         return self.create(request)
 
 class StuMixinViews(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
     queryset = models.Student.objects.all()
     serializer_class = StuModelSer
 
     def get(self, request, pk):  # 查询一条数据
         return self.retrieve(request, pk=pk)
 
     def put(self, request, pk):  # 修改一条数据
         return self.update(request, pk=pk)
 
     def delete(self, request, pk):  # 删除一条数据
         return self.destroy(request, pk=pk)
 
 #2.urls.py
 urlpatterns = [
     # APIView
     path('stu/', views.StuApiView.as_view()),
     re_path(r'^stu/(?P\d+)/#39;, views.StuApiViews.as_view()),
 
     # GenericAPIView
     path('gstu/', views.StuGenericAPIView.as_view()),
     re_path(r'^gstu/(?P\d+)/#39;, views.StuGenericAPIViews.as_view()),
 
     # mixins
     path('mstu/', views.StuMixinView.as_view()),
     re_path(r'^mstu/(?P\d+)/#39;, views.StuMixinViews.as_view()),
 ]

9个视图子类

具体的通用视图。通常情况下,你应该都是使用的它们,除非需要高度的自定义行为。

 ListAPIView = GenericAPIView + ListModelMixin #获取多条数据
 RetrieveAPIView = GenericAPIView + RetrieveModelMixin #获取一个数据
 CreateAPIView =  GenericAPIView + CreateModelMixin #添加一条数据
 UpdateAPIView = GenericAPIView + UpdateModelMixin #更新一条数据
 DestroyAPIView = GenericAPIView + DestroyModelMixin #删除一条数据
 
 #组合视图子类
 ListCreateAPIView = ListAPIView + CreateAPIView
 RetrieveUpdateAPIView = RetrieveAPIView + UpdateAPIView
 RetrieveDestroyAPIView = RetrieveAPIView + DestroyAPIView
 RetrieveUpdateDestroyAPIView = RetrieveAPIView + UpdateAPIView + DestroyAPIView

CreateAPIView

仅用于创建实例。提供一个 post 请求的处理方法。继承自:GenericAPIView, CreateModelMixin

ListAPIView

仅用于读取模型实例列表。提供一个 get 请求的处理方法。继承自:GenericAPIView, ListModelMixin

RetrieveAPIView

仅用于查询单个模型实例。提供一个 get 请求的处理方法。继承自:GenericAPIView, RetrieveModelMixin

DestroyAPIView

仅用于删除单个模型实例。提供一个 delete 请求的处理方法。继承自:GenericAPIView, DestroyModelMixin

UpdateAPIView

仅用于更新单个模型实例。提供 putpatch 请求的处理方法。继承自:GenericAPIView, UpdateModelMixin

ListCreateAPIView

既可以获取也可以实例集合,也可以创建实例列表。提供 getpost 请求的处理方法。继承自:GenericAPIView, ListModelMixinCreateModelMixin

RetrieveUpdateAPIView

既可以查询也可以更新单个实例。提供 getputpatch 请求的处理方法。继承自:GenericAPIView, RetrieveModelMixinUpdateModelMixin

RetrieveDestroyAPIView

既可以查询也可以删除单个实例。提供 getdelete 请求的处理方法。继承自:GenericAPIView, RetrieveModelMixinDestroyModelMixin

RetrieveUpdateDestroyAPIView

同时支持查询,更新,删除。提供 getputpatchdelete 请求的处理方法。继承自:GenericAPIView, RetrieveModelMixinUpdateModelMixinDestroyModelMixin

使用示例

 #model.py和serializer.py的内容跟APIview一样
 
 #1.views.py
 from rest_framework.generics import (
     ListAPIView,
     CreateAPIView,
     RetrieveAPIView,
     UpdateAPIView,
     DestroyAPIView,
     ListCreateAPIView,
     RetrieveUpdateAPIView,
     RetrieveDestroyAPIView,
     RetrieveUpdateDestroyAPIView,
 )
 
 # 获取所有和添加一条数据的视图类
 class StudentSonView(ListCreateAPIView):
     queryset = models.Student.objects.all()
     serializer_class = StuModelSer
 
 # 获取一条,修改一条,删除一条的视图类
 class StudentSonViews(RetrieveUpdateDestroyAPIView):
     queryset = models.Student.objects.all()
     serializer_class = StuModelSer
 
 #2.urls.py
 urlpatterns = [
 ...
     # 视图子类
     path('sstu/', views.StudentSonView.as_view()),
     re_path(r'^sstu/(?P\d+)/#39;, views.StudentSonViews.as_view()),
 ]
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章