Django REST framework--类视图

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Django REST framework--类视图

基于类的视图

项目开发中要不断思考如何让代码保持高内聚低耦合因此优化代码的道路上一直都不停歇。目前开发的视图是基于函数形式的特点是灵活缺点是功能冗余性大面对常见的增删改查往往要写重复的代码。

REST框架可以用基于类的视图来优化代码结构

APIView类视图

用类重写视图继承REST框架的APIView类

sqtp应用app目录下的views.py文件下将request_listrequest_detail两个视图函数修改为类视图

from django.shortcuts import render

# Create your views here.

from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt    # 跨站攻击防护接口白名单处理
from rest_framework import status
from rest_framework.parsers import JSONParser       # 序列化
from rest_framework.response import Response

from sqtp.models import Request     # 模型
from sqtp.serializers import RequestSerializer      # 自定义的序列化类
from rest_framework.decorators import api_view
from rest_framework.views import APIView  # 继承APIView类视图

# 改写 request_list 视图方法
class RequestList(APIView):
    '''
    查询所有数据和新增单个数据的功能
    '''
    def get(self,request,format=None):
        # 获取序列化器--针对当前数据模型的所有数据
        serializer = RequestSerializer(Request.objects.all(), many=True)
        return Response(serializer.data)  # 使用DRF框架的响应对象自动分配返回格式

    # 处理新增请求
    def post(self,request,format=None):
        # 构建序列化器,反序列化,将request.data数据恢复成正常的对象实例
        serializer = RequestSerializer(data=request.data)
        # 校验数据是否合法
        if serializer.is_valid():
            serializer.save()
            # 新增成功返回新增数据状态码201
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        # 新增失败返回错误信息400,请求数据有问题
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


# 改写 request_detail 视图方法
class RequestDetail(APIView):

    # 覆盖父类的get_object方法实现
    def get_object(self,_id):
        try:
            return Request.objects.get(id=_id)
        except Exception:
            return Response(status=status.HTTP_404_NOT_FOUND)  # 返回错误状态码

    def get(self,request,_id,format=None):
        # 序列化将数据对象转化为json格式
        req_boj = self.get_object(_id)
        # 如果是异常响应直接返回
        if isinstance(req_boj,Response):
            return req_boj
        serializer = RequestSerializer(req_boj)
        return Response(data=serializer.data)

    def put(self,request,_id,format=None):
        # 采用序列化器实现修改这里与查询不同的是还需要把待修改的数据放到序列化器里进行覆盖
        req_boj = self.get_object(_id)
        # 如果是异常响应直接返回
        if isinstance(req_boj, Response):
            return req_boj
        serializer = RequestSerializer(req_boj, data=request.data)
        # 判断data中的数据是否符合要求
        if serializer.is_valid():
            # 若符合要求则进行保存操作
            serializer.save()
            # 将修改成功的状态码返回
            return Response(serializer.data, status=status.HTTP_200_OK)
        # 修改失败返回错误信息400,修改传递的数据有问题
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self,request,_id,format=None):
        req_boj = self.get_object(_id)
        # 如果是异常响应直接返回
        if isinstance(req_boj, Response):
            return req_boj
        req_boj.delete()  # 获取数据后进行删除
        # 将删除成功的状态码返回
        return Response(status=status.HTTP_204_NO_CONTENT)

修改sqtp应用app目录下的urls.py文件

from django.urls import path
from sqtp import views as sqtp_view
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
  path('requests/',sqtp_view.RequestList.as_view()),  # 视图类需要调用 as_view转化
  path('requests/<int:_id>',sqtp_view.RequestDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns) # 重写url

行命令python manage.py runserver 0.0.0.0:8888启动项目在浏览器中输入http://127.0.0.1:8888/requests/可以发现页面返回内容与视图函数是一样的

generics通用类视图

使用类视图的一个好处就是可以复用相同的功能只需传入指定的参数即可。在上面的案例中增删改查的逻辑行为都是确定的。

REST框架为我们封装好了逻辑可以用更少的代码来封装视图比如采用generics模块的通用视图通过generics.ListCreateAPIViewm 实现列出所有和新增通过generics.RetrieveUpdateDestroyAPIView获取单个、更新和删除功能

sqtp应用app目录下的views.py文件下将request_listrequest_detail两个视图函数修改为generics通用类视图

from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView   # 继承generics通用类视图

# 改写 request_list 视图方法
class RequestList(ListCreateAPIView):
    queryset = Request.objects.all()    # 数据的查询集
    serializer_class = RequestSerializer


# 改写 request_detail 视图方法
class RequestDetail(RetrieveUpdateDestroyAPIView):
    queryset = Request.objects.all()  # 数据的查询集
    serializer_class = RequestSerializer

由于是 RequestDetail视图类是继承RetrieveUpdateDestroyAPIView类所以参数id的名称要为pk这是底层代码GenericAPIView类中的要求限制lookup_field = 'pk'

否则浏览器中输入http://127.0.0.1:8888/requests/43就会产生报错提示修改url配置

AssertionError: Expected view RequestDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.

修改sqtp应用app目录下的urls.py文件将requests/<int:_id>修改为requests/<int:pk>

from django.urls import path
from sqtp import views as sqtp_view
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
  path('requests/',sqtp_view.RequestList.as_view()),  # 视图类需要调用 as_view转化
  path('requests/<int:pk>',sqtp_view.RequestDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns) # 重写url

重启服务测试增删改查依然OK

可以发现数据详情的编辑页面还支持按字段进行编辑这是通用类视图提供的效果。

在这里插入图片描述

视图集

通过使用generics通用类视图代码量已经减少到了不到10行优化后的视图代码依然存在重复的部分这部分的代码依旧可以继续优化用ViewSet视图集代替View类重构视图

sqtp应用app目录下的views.py文件下将RequestLisRequestDetail两个视图类修改一个

from rest_framework import viewsets

class RequestViewSet(viewsets.ModelViewSet):
    queryset = Request.objects.all()  # 数据的查询集
    serializer_class = RequestSerializer

使用REST ViewSets 的抽象后开发人员可以集中精力对API的状态和交互进行建模并根据常规约定自动处理URL构造。

ViewSet 类与 View 类几乎相同不同之处在于它们提供诸如 read 或 update 之类的操作而不是 get 或 put 等方法处理程序。

一个 ViewSet 类只绑定到一组方法处理程序当它被实例化成一组视图的时候通常通过使用一个 Router 类来代替自己定义复杂的URL。

DRF框架路由

因为使用的是 ViewSet 类而不是 View 类所以连常规的URL设计都可以偷懒了。利用rest框架 的router可以自动生成路由列表。

修改sqtp应用app目录下的urls.py文件

from django.urls import path,include
from sqtp import views as sqtp_view
# 使用rest框架自带的路由器生成路由列表
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'requests',sqtp_view.RequestViewSet)

urlpatterns = [
    path('',include(router.urls))
]

router的作用是根据注册的路由前缀帮助你自动生成诸如此类的路由列表根据正则匹配参数、后缀等内容

^requests/$ [name='request-list']
^requests\.(?P<format>[a-z0-9]+)/?$ [name='request-list']
^requests/(?P<pk>[^/.]+)/$ [name='request-detail']
^requests/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='request-detail']

重启服务测试增删改查依然OK

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go

“Django REST framework--类视图” 的相关文章