专栏首页小闫笔记DRF框架学习(三)

DRF框架学习(三)

DRF框架学习(三)

1.视图

1.1作用

1.控制序列化器的执行(数据检验、数据保存、转换数据(序列化操作))

2.控制数据库的查询操作。

1.2类视图的两个基类

1.2.1APIView

是View类的子类,在view类的基础上添加了一些额外的功能。

功能

1.视图中的request对象不再是Django中 HttpRequest类的对象,而是由DRF框架封装成的 Request类的对象。

2.响应时可以统一返回Response类的对象

3.异常处理:如果视图中抛出了未处理异常,DRF框架会自动对异常进行处理,并且会把处理之后的错误信息返回给客户端。例如 Http404这个系统处理过的处理异常的方法,我们直接将它抛出,客户端就可以收到处理之后的错误信息,不会是404页面,而是错误信息,如“未找到“。

4.高级功能:

1)认证

2)权限

3)限流

Request类的对象

1. request.data里面保存解析之后的请求体数据,并且已经解析成了字典或类字典,相当于包含了Django原始request对象中的 request.body|request.POST|request.FILES

2. query_params:保存解析之后的查询字符串数据,并且已经解析成了字典或类字典。 request.query_params与Django标准的 request.GET相同,只是更换了更正确的名称而已。

Response类的对象

1.传入原始相应数据(比如一个字典),Response会自动根据客户端请求头中 Accept将相应数据转换为对应的格式进行返回。默认是json格式。也可以指定返回的是网页,只需要将Accept设置为 text/html即可。但是仅仅支持json和html两种。

为了方便设置状态码,REST framewrok在 rest_framework.status模块中提供了常用状态码常量,我们直接使用即可。

status = status.HTTP_201_CREATED

上面的就可以指定201状态码了,我们直接写201的话,其他人容易看不懂,我们用常量让人易于理解。

1.2.2GenericAPIView

继承于APIView,是APIView的子类,在APIView的基础上添加操作序列化器和数据库查询的方法。封装的这些方法,我们可以直接使用。

补充知识点

1.类视图对象有一个属性: self.kwargs,它是一个字典,保存的是从url地址中提取的所有命名参数。它的作用:比如我们定义了一个视图,没有形参接收传递的参数,那么我们可以使用 self.kwargs从url地址中提取我们需要的数据。

2. queryset指定当前视图所使用的查询集;

serializer_class指定当前视图所使用的序列化器类;

self.serializer_class获取当前视图所使用的序列化器类;

serializer_cls=self.get_serializer_class()获取当前视图所使用的序列化器类;

serializer_cls(*args,**kwargs)创建一个序列化器类对象。

# 自定义一个GenericAPIView
class MyGenericAPIView(APIView):
    queryset = None
    serializer_class = None

    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'

    def get_serializer_class(self):
        return self.serializer_class
    def get_serializer(self,*args,**kwargs):
        serializer_cls = self.get_serializer_class()
        return serializer_cls(*args,**kwargs)
    def get_queryset(self):
        return self.queryset.all()
    def get_object(self):
        #从视图所使用的查询集中获取指定的对象,默认根据pk进行查询
        # 获取当前视图所使用的查询集
        query_set = self.get_queryset() # QuerySet
        # filters = {'pk':self.kwargs['pk']}
        filters = {self.lookup_field:self.kwargs[self.lookup_url_kwarg]}
        try:
            # obj = query_set.get(pk=self.kwargs['pk])
            obj = query_set.get(**filters)
        except Exception:
            raise Http404
        return obj

操作序列化器

a)属性

serializer_class指定当前视图所使用的序列化器类。

b)方法

get_serializer创建一个视图所使用序列化器类的对象。

get_serializer_class返回当前视图所使用的序列化器类。

数据库查询

a)属性

queryset(指定视图所使用的查询集)

b)方法

get_queryset获取当前视图所使用的查询集。

get_object从视图所使用的查询集中查询指定的对象,默认根据pk(查询)进行查询。

其他功能:

a)过滤

b)分页

补充知识点

查询的时候我们想不根据主键pk查询,而是根据我们的需求查,那么可以根据修改 lookup_field(值改为我们要查询的字段的名称)的值来解决需求。

lookup_url_kwarg指定从查询集获取对象时,从url地址中提取的参数的名称。

注意:经常配合Minxin扩展类来使用。

1.3Mixin扩展类(重要)

class MyListModelMixin(object):
    def list(self,request,*args,**kwargs):
        """获取一组数据的通用代码"""
        .....
class MyCreateModelMixin(object):
    def create(self,request,*args,**kwargs):
        """创建一条数据的通用代码"""
        ...
class MyRetrieveModelMixin(object):
    def retrieve(self,request,*args,**kwargs):
        """获取指定的对象数据的通用过程"""

自己抽取代码实现扩展类的步骤:

1)先将通用的代码抽取出来。

2)创建一个扩展类,将抽取的代码进行封装。

3)在原视图函数中进行调用。

1.3.1扩展类5个详解

DRF框架提供了5个扩展类,封装了通用增删改查的流程。

1.3.1.1ListModelMixin

列表视图扩展类,提供 list(request,*args,**kwargs)方法快速实现列表视图,返回200状态码。

该Mixin的list方法会对数据进行过滤和分页。

源代码:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        # 过滤
        queryset = self.filter_queryset(self.get_queryset())
        # 分页
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        # 序列化
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

举例:

from rest_framework.mixins import ListModelMixin

class BookListView(ListModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request):
        return self.list(request)

1.3.1.2CreateModelMixin

创建视图扩展类,提供 create(request,*args,**kwargs)方法快速实现创建资源的视图,成功返回201状态码。

如果序列化器对前端发送的数据验证失败,返回400错误。

源代码:

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        # 获取序列化器
        serializer = self.get_serializer(data=request.data)
        # 验证
        serializer.is_valid(raise_exception=True)
        # 保存
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

1.3.1.3RetrieveModelMixin

详情视图扩展类,提供 retrieve(request,*args,**kwargs)方法,可以快速实现返回一个存在的数据对象

如果存在,返回200, 否则返回404。

源代码:

class RetrieveModelMixin(object):
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        # 获取对象,会检查对象的权限
        instance = self.get_object()
        # 序列化
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

举例:

class BookDetailView(RetrieveModelMixin, GenericAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request, pk):
        return self.retrieve(request)

1.3.1.4UpdateModelMixin

更新视图扩展类,提供 update(request,*args,**kwargs)方法,可以快速实现更新一个存在的数据对象

同时也提供 partial_update(request,*args,**kwargs)方法,可以实现局部更新。

成功返回200,序列化器校验数据失败时,返回400错误。

源代码:

class UpdateModelMixin(object):
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

1.3.1.5DestroyModelMixin

删除视图扩展类,提供 destroy(request,*args,**kwargs)方法,可以快速实现删除一个存在的数据对象

成功返回204,不存在返回404。

源代码:

class DestroyModelMixin(object):
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

1.3.2子类视图类

1.3.2.1CreateAPIView

提供 post 方法

继承自: GenericAPIView、CreateModelMixin

1.3.2.2ListAPIView

提供 get 方法

继承自:GenericAPIView、ListModelMixin

1.3.2.3RetrieveAPIView

提供 get 方法

继承自: GenericAPIView、RetrieveModelMixin

1.3.2.4DestoryAPIView

提供 delete 方法

继承自:GenericAPIView、DestoryModelMixin

1.3.2.5UpdateAPIView

提供 put 和 patch 方法

继承自:GenericAPIView、UpdateModelMixin

1.3.2.6ListCreateAPIView

提供 get 和 post 方法

继承自:GenericAPIView、ListModelMixin、CreateModelMixin

1.3.2.7RetrieveUpdateAPIView

提供 get、put、patch方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

1.3.2.8RetrieveDestroyAPIView

提供 get 和 delete 方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin

1.3.2.9RetrieveUpdateDestoryAPIView

提供 get、put、patch、delete方法

继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

公司中如果不知道该继承哪一个类,那么就继承APIView,完成了需求之后我们再进行代码的优化。时间长了之后,就知道该怎么写最简单的代码了。

2.视图集

2.1概念

将操作同一组资源的处理方法(API接口)同一个类中。(重要)

2.2注意点

1、视图集中的处理方法不再是以请求方式命名,而是以对应的操作名称(list、create、update、retrieve、destroy)

2、在进行url配置的时候,要指明请求地址的请求方式和视图集中处理函数之间的对应关系。

2.3视图集父类

ViewSet

继承自ViewSetMixin和APIView

GenericViewSet

使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖与 GenericAPIView,所以还需要继承 GenericAPIView

GenericViewSet就帮助我们完成了这样的继承工作,继承自 GenericAPIViewViewSetMixin,在实现了调用as_view()时传入字典(如 {'get':'list'})的映射处理工作的同时,还提供了 GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用。

ModelViewSet

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

ReadonlyModelViewSet

继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

2.4视图集中添加额外的处理方法

1、直接在视图集中定义额外的处理方法即可

2、在进行url配置的时候指定请求地址请求方式和处理函数之间的对应的关系。

本文分享自微信公众号 - 全栈技术精选(Pythonnote),作者:小闫同学啊

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 项目阶段之flask(五)

    1/取出表单中的csrf_token(加密的),使用SECRET_KET解密csrf_token,得到未加密的csrf_token

    小闫同学啊
  • 扒源码 - 一个请求在flask中经历了什么

    客户端发起一个请求,Flask 都干了什么呢?url 如何与视图进行绑定的?更多精彩文章请关注公众号『Pythonnote』或者『全栈技术精选』

    小闫同学啊
  • python技术面试题(十七)

    People will forget what you said, people will forget what you did, but people wi...

    小闫同学啊
  • 线性代数与张量?这本开放书籍帮你扫清通往ML的数学绊脚石

    项目地址:https://web.stanford.edu/~boyd/vmls/

    机器之心
  • dotnet 在 GitHub 的 Action 上部署自动代码编码规范机器人

    我们的项目中会包含有很多文件,但是可能我们没有注意到的,我们的文件的编码不一定是 UTF-8 编码,这就可能让构建出来的应用程序在别人电脑运行时出现乱码,或者别...

    林德熙
  • 渐进式Web应用入门-ServiceWorker

    用户1907613
  • python中的@ 装饰器 闭包 切片式编程

      一个修饰符就是一个函数,它将被修饰的函数作为参数,并返回修饰后的同名函数或其他可调用的东西?

    战神伽罗
  • Android自动化测试探索(五)代码覆盖率统计

    同样如果以上说的几个都不懂也行, 让开发帮忙做这些然后编个代码覆盖率统计的包给你测试, 测完把手机给开发取数据生成报告。 注意每次测试完先返回手机桌面把程序退到...

    周希
  • sudo apt-get 与 yum安装有啥区别

    用户1518699
  • 作为一位资深程序员,你一年中有多少天是准时下班的?如何看待这份工作?

    作为已经写了十几年代码的老程序员,准时下班的次数现在看少的可怜,倒是刚毕业进的第一家公司属于外企性质,有很多次的准时下班的经历,结果随着技术能力提升以及经验的增...

    程序员互动联盟

扫码关注云+社区

领取腾讯云代金券