前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DRF框架学习(三)

DRF框架学习(三)

作者头像
小闫同学啊
发布2019-07-18 11:37:09
1.1K0
发布2019-07-18 11:37:09
举报
文章被收录于专栏:小闫笔记小闫笔记

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模块中提供了常用状态码常量,我们直接使用即可。

代码语言:javascript
复制
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)创建一个序列化器类对象。

代码语言:javascript
复制
# 自定义一个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扩展类(重要)

代码语言:javascript
复制
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方法会对数据进行过滤和分页。

源代码:

代码语言:javascript
复制
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)

举例:

代码语言:javascript
复制
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错误。

源代码:

代码语言:javascript
复制
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。

源代码:

代码语言:javascript
复制
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)

举例:

代码语言:javascript
复制
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错误。

源代码:

代码语言:javascript
复制
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。

源代码:

代码语言:javascript
复制
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
代码语言:javascript
复制
提供 post 方法

继承自: GenericAPIView、CreateModelMixin
1.3.2.2ListAPIView
代码语言:javascript
复制
提供 get 方法

继承自:GenericAPIView、ListModelMixin
1.3.2.3RetrieveAPIView
代码语言:javascript
复制
提供 get 方法

继承自: GenericAPIView、RetrieveModelMixin
1.3.2.4DestoryAPIView
代码语言:javascript
复制
提供 delete 方法

继承自:GenericAPIView、DestoryModelMixin
1.3.2.5UpdateAPIView
代码语言:javascript
复制
提供 put 和 patch 方法

继承自:GenericAPIView、UpdateModelMixin
1.3.2.6ListCreateAPIView
代码语言:javascript
复制
提供 get 和 post 方法

继承自:GenericAPIView、ListModelMixin、CreateModelMixin
1.3.2.7RetrieveUpdateAPIView
代码语言:javascript
复制
提供 get、put、patch方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
1.3.2.8RetrieveDestroyAPIView
代码语言:javascript
复制
提供 get 和 delete 方法

继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
1.3.2.9RetrieveUpdateDestoryAPIView
代码语言:javascript
复制
提供 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

代码语言:javascript
复制
继承自ViewSetMixin和APIView

GenericViewSet

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

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

ModelViewSet

代码语言:javascript
复制
继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。

ReadonlyModelViewSet

代码语言:javascript
复制
继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin。

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈技术精选 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DRF框架学习(三)
    • 1.视图
      • 1.1作用
      • 1.2类视图的两个基类
      • 1.3Mixin扩展类(重要)
    • 2.视图集
      • 2.1概念
      • 2.2注意点
      • 2.3视图集父类
      • 2.4视图集中添加额外的处理方法
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档