前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DRF二级视图GenericAPIView

DRF二级视图GenericAPIView

作者头像
zy010101
发布2021-12-17 20:28:36
6440
发布2021-12-17 20:28:36
举报
文章被收录于专栏:程序员程序员

GenericAPIView

GenericAPIView继承自APIView,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。

属性

基本设置:

以下属性控制基本视图行为。

列表视图:获取多条数据(或全部数据),例如:获取所有书籍

详情视图:获取单个数据,例如:获取《西游记》的价格,作者,出版社等信息。

列表视图与详情视图通用
  • queryset 应用于从此视图返回对象的查询集。通常,您必须设置此属性或覆盖该get_queryset()方法。如果您要覆盖视图方法,请务必调用get_queryset()而不是直接访问此属性。
  • serializer_class 应该用于验证和反序列化输入以及序列化输出的序列化器类。通常,您必须设置此属性或覆盖该get_serializer_class()方法。
详情视图使用
  • lookup_field 应该用于执行单个模型实例的对象查找的模型字段。默认为’pk’.
  • lookup_url_kwarg 应该用于对象查找的 URL 关键字参数。URL conf 应包含与此值对应的关键字参数。如果未设置,则默认使用lookup_field.

分页

以下属性用于在与列表视图一起使用时控制分页。

  • pagination_class 分页列表结果时应使用的分页类。默认为与DEFAULT_PAGINATION_CLASS设置相同的值,即’rest_framework.pagination.PageNumberPagination’。设置pagination_class=None将禁用此视图的分页。

过滤

  • filter_backends 应用于过滤查询集的过滤器后端类列表。默认值与DEFAULT_FILTER_BACKENDS设置相同。

方法

列表视图与详情视图通用

get_queryset(self) 返回视图使用的查询集,是列表视图与详情视图获取数据的基础,默认返回queryset属性,可以重写,例如:

代码语言:javascript
复制
def get_queryset(self):
    return BookInfo.objects.all()

get_serializer_class(self) 返回序列化器类,默认返回serializer_class,可以重写,例如:

代码语言:javascript
复制
def get_serializer_class(self):
    return BookInfoModelSerializer

get_serializer(self, _args, *_kwargs)返回序列化器对象,被其他视图或扩展类使用,如果我们在视图中想要获取序列化器对象,可以直接调用此方法。

详情视图使用

get_object(self) 返回详情视图所需的模型类数据对象,默认使用lookup_field参数来过滤queryset。 在视图中可以调用该方法获取详情信息的模型类对象。

若详情访问的模型类对象不存在,会返回404。

经验:GenericAPIView看起来是非常美好的,可以和各个mixin结合起来使用,但是实际上用处不大。因为这样最多是开发速度提高,但是如果产品修改了需求,相应的序列化器就得改。然后有的接口需要A序列化器进行数据检验,有的需要B序列化器,GenericAPIView这时候改起来就很不方便。

建议:使用FVB模式进行开发,这样便于修改,或者是每一个CVB中只有一个方法,但是这样不如直接使用FVB。

下面来举一些例子。这些例子中有些用到了分页器。这并不影响我们的理解。如果不清楚DRF分页器的,可以看这里

列表和新增视图

列表视图中,每次按照分页大小返回多个数据。如下图所示,我们使用百度搜索的时候,百度会以分页的形式给我们展示数据。

在这里插入图片描述
在这里插入图片描述

我们的列表视图代码如下:

代码语言:javascript
复制
class PageNum(PageNumberPagination):
    """分页器类"""
    page_size = 10  # 默认每页返回的条数
    page_query_param = 'pagenum'     #url中设置 page 的键,默认为page
    page_size_query_param = 'pagesize'  # url中设置 page_size 的键,默认为page_size
    max_page_size = 50  # 每页返回的最大条数


class BookListView(GenericAPIView):
    """列表视图"""
    queryset = BookInfo.objects.all().order_by('id')
    serializer_class = BookInfoSerializer
    pagination_class = PageNum


    def get(self, request):
        """GET请求获取列表"""
        data = self.get_queryset()      # 获取查询结果集
        page = self.paginate_queryset(data)    #对查询结果集进行分页
        serializer = self.get_serializer(page, many=True)   # 序列化
        return Response(serializer.data)    # 返回值


    def post(self, request):
        """post请求新增"""
        data = request.data
        serializer = self.get_serializer(data=data)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data, status=201)
        else:
            # 返回错误信息
            return Response({'msg': '保存失败'}, status=400)

使用GET方法请求,效果如下:

在这里插入图片描述
在这里插入图片描述

新增成功,返回的响应如下所示:

在这里插入图片描述
在这里插入图片描述

把列表方法和新增方法放在一个类中的原因是“这两者使用的URL是相同的,而后面的查询一条数据详情,修改一条已有数据,删除一条数据的URL是相同的。”

删改查视图

该视图将包含删除一条数据,修改一条数据以及获取一条数据的详细信息这三个功能,对应的HTTP请求方法分别是DELETE,PUT和GET。它们会使用同样的URL。

代码语言:javascript
复制
class BookView(GenericAPIView):
    """删改查视图"""
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'

    def get(self, request, pk):
        """根据id查询书籍详情"""
        obj = self.get_object()
        serializers = self.get_serializer(obj)

        return Response(serializers.data)

    def delete(self, request, pk):
        """根据id删除书籍"""
        obj = self.get_object()
        obj.delete()

        return Response(status=204)

    def put(self, request, pk):
        """根据id修改某一本书籍信息"""
        obj = self.get_object()
        data = request.data
        serializers = self.get_serializer(obj, data)
        if serializers.is_valid(raise_exception=True):
            serializers.save()
            # PUT更新,如果返回数据,建议状态码为200;如果不返回数据,状态码根据情况可选择204或者205
            return Response(serializers.data, status=200)   
        else:
            return Response(status=400)

我们的URL设计如下所示:

代码语言:javascript
复制
path('book', BookListView.as_view()),
path('book/<int:pk>', BookView.as_view()),

使用http://127.0.0.1:8848/book/3进行请求,返回的响应如下:

在这里插入图片描述
在这里插入图片描述

这样就基本体现了RESTFul的设计思路。URL中只涉及名词,接口被统一,使用HTTP请求方法来区分动作。不同的HTTP方法就代表着对资源的不同操作。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-12-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • GenericAPIView
    • 属性
      • 基本设置:
      • 分页
      • 过滤
    • 方法
      • 列表视图与详情视图通用
      • 详情视图使用
    • 列表和新增视图
      • 删改查视图
      相关产品与服务
      文件存储
      文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档