drf视图类关系详解(代码片段)

franciszw franciszw     2022-12-06     291

关键词:

概要:
# 1 请求和响应
# 2 请求 Request对象,drf新包装的,Request.data,Request.query_params, 重写了__getattr__,  request._request
# 3 json模块是否执行反序列化bytes格式
# 4 考你:视图类的方法中:self.request,就是当次请求的request

# 5 Response:类,实例化传一堆参,data=字典,status=状态码(有一堆常量),headers=响应头(字典),content_type=响应的编码方式
# 6 全局和局部配置,响应格式
# 7 drf默认配置文件,查找顺序--》先从类中属性找---》项目的setting找---》drf默认的配置找


# 8 视图家族
	-APIView---》继承自View
    -GenicAPIView---》APIView,做了一些扩展:
    	-queryset = None
    	-serializer_class = None
        -get_queryset()  经常用
        -get_serializer() 经常用
        -get_serializer_class() 内部来用,外部会重写
        -get_object()  经常用,获取一条数据(pk传过来)
        	-源码解析
            queryset = self.filter_queryset(self.get_queryset()) #返回所有数据queryset对象
            # lookup_url_kwarg就是pk,路由中有名分组分出来的pk
            lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
            # pk:4  4 浏览器地址中要查询的id号http://127.0.0.1:8000/books6/4/
            filter_kwargs = self.lookup_field: self.kwargs[lookup_url_kwarg]
            # 根据pk=4去queryset中get单个对象
            obj = get_object_or_404(queryset, **filter_kwargs)
            self.check_object_permissions(self.request, obj)
            return obj
   -5 个视图扩展类(继承了object),每个里面写了一个方法(ListModelMixin:list方法)		
        ListModelMixin,
        CreateModelMixin,
        UpdateModelMixin,
        DestroyModelMixin,
        RetrieveModelMixin
   -GenericAPIView的视图子类,9个,继承了GenicAPIView+一个或者两个或者三个视图扩展类
        CreateAPIView,
        ListAPIView,
        UpdateAPIView,
        RetrieveAPIView,
        DestroyAPIView,
        ListCreateAPIView,
        RetrieveUpdateDestroyAPIView,
        RetrieveDestroyAPIView,
        RetrieveUpdateAPIView
  -视图集:ModelViewSet,ReadOnlyModelViewSet:继承了上面一堆(5个视图扩展和GenicAPIView)+自己写了一个ViewSetMixin(as_view方法),只要继承它的,路由得写成‘get’:‘自己定义的方法’
	-ViewSet=ViewSetMixin, views.APIView :ViewSetMixin要放在前面
    -GenericViewSet=ViewSetMixin+GenicAPIView
    
    -ViewSetMixin(as_view方法)
    -ViewSetMixin+APIView=ViewSet
    -ViewSetMixin+GenicAPIView=GenericViewSet

1 请求和响应

1.1请求

  • 1.1.1,认证类的两个request
源码:
def view(request, *args, **kwargs):
    self = cls(**initkwargs)
    if hasattr(self, ‘get‘) and not hasattr(self, ‘head‘):
        self.head = self.get
    self.request = request #将原生的request赋值各了对象,类的对象可以通过self.取到request
    self.args = args
    self.kwargs = kwargs
    return self.dispatch(request, *args, **kwargs)#函数返回了request所以视图函数可以接收request
  • 1.1.2 经过APIView时,rest_framework重新封装了request

    导入使用: from rest_framework.request import Request

# 源码分析
1,重写了init方法对象装饰时字典将原request作为新request的属性
    def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        
        # 二次封装request,将原生request作为drf request对象的 _request 属性
        self._request = request
        
2,重写了getattr方法,获取新request的属性时先去原request里查找       
    def __getattr__(self,item):
    	return getattr(self._request,item)
# 请求对象.data:前端以三种编码方式传入的数据,都可以取出来
# 请求对象..query_params 与Django标准的request.GET相同,只是更换了更正确的名称而已。

1.2响应

rest_framework重新封装了response,

导入:from rest-framework.response import Response

源码分析:
def __init__(self, data=None, status=None,
                 template_name=None, headers=None,
                 exception=False, content_type=None):
        
#data:你要返回的数据,字典
#status:返回的状态码,默认是200,
	-from rest_framework import status在这个路径下,它把所有使用到的状态码都定义成了常量
#template_name 渲染的模板名字(自定制模板)
#headers:响应头,可以往响应头放东西,就是一个字典
#content_type:响应的编码格式,application/json和text/html;

# 浏览器响应成浏览器的格式,postman响应成json格式,通过配置实现的(默认配置)
#不管是postman还是浏览器,都返回json格式数据

drf配置文件的查找顺序:
# drf的配置信息,先从自己类中找--》项目的setting中找---》默认的找
	-局部使用:对某个视图类有效
        -在视图类中写如下,drf会优先使用自己类的配置,只对自己的类有效
        from rest_framework.renderers import JSONRenderer
        renderer_classes=[JSONRenderer,]
        
    -全局使用:全局的视图类,所有请求,都有效
    	-在setting.py中加入如下
        REST_FRAMEWORK = 
            ‘DEFAULT_RENDERER_CLASSES‘: (  # 默认响应渲染类
                ‘rest_framework.renderers.JSONRenderer‘,  # json渲染器
                ‘rest_framework.renderers.BrowsableAPIRenderer‘,  # 浏览API渲染器
            )
        
  • 1.2.1自己封装一个response对象

2 视图

2.1 基于APIView写接口:

1,手动写orm语句

book_list=Book.objects.all()

2,手动调用序列化器

book_ser=BookSerializer(book_list,many=True)

3,手动写业务逻辑处理不同的请求

def get(self,request):

def post(self,request):

4,视图的类需要写两个,分别对应url的有名分组传参和不传参情况.

url(r‘^api/books2/$‘, views.Books2.as_view()),
url(r‘^api/book2/(?P<num>d+)/‘, views.Book2.as_view())
class BookView(APIView):
    def get(self,request):
        book_list=Book.objects.all()
        book_ser=BookSerializer(book_list,many=True)

        return Response(book_ser.data)
    def post(self,request):
        book_ser = BookSerializer(data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response(‘status‘:101,‘msg‘:‘校验失败‘)


class BookDetailView(APIView):
    def get(self, request,pk):
        book = Book.objects.all().filter(pk=pk).first()
        book_ser = BookSerializer(book)
        return Response(book_ser.data)

    def put(self, request,pk):
        book = Book.objects.all().filter(pk=pk).first()
        book_ser = BookSerializer(instance=book,data=request.data)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.data)
        else:
            return Response(‘status‘: 101, ‘msg‘: ‘校验失败‘)

    def delete(self,request,pk):
        ret=Book.objects.filter(pk=pk).delete()
        return Response(‘status‘: 100, ‘msg‘: ‘删除成功‘)

下面的类分别解简化了上述步骤大量减少代码的书写:

2.2 基于GenericAPIView写的接口:

简化步骤,在类里直接申明了操作哪张表,调用哪个序列化器:

queryset = models.Booklib.objects
serializer_class = BookModelSerializer

在请求的函数种调用申明的列表和序列化器会自动传入对象

book=self.get_queryset().filter(pk=num).first()
ser_obj=self.get_serializer(book)

下面分别对应5种方法的注意事项:

  • queryset只有一个对象时有个大坑,需要用.first()取到
  • 反序列化数据化后要判断数据是否合法,调用序列化器的save方法
  • 多条数据序列化用many=True
class Books2(GenericAPIView):

    queryset = models.Booklib.objects.all()
    serializer_class = BookModelSerializer

    def get(self,request):

        book=self.get_queryset()
        book_ser=self.get_serializer(book,many=True)

        return CommomResponse(data=book_ser.data,headers=‘key‘:‘value‘)


    def post(self,request):#创建,修改了id为只读属性,创建时不需要id参数
        book_ser=self.get_serializer(data=request.data)

        if book_ser.is_valid():
            book_ser.save()

            return CommomResponse(data=book_ser.data)
        else:

            return CommomResponse(101,‘数据不和法‘,book_ser.errors)

class Book2(GenericAPIView):
    queryset = models.Booklib.objects
    serializer_class = ser.BookModelSerializer

    def get(self,request,num):
        book=self.get_queryset().filter(pk=num).first()
        ser_obj=self.get_serializer(book)

        return CommomResponse(data=ser_obj.data)


    def delete(self,request,num):
        book=self.get_queryset().filter(pk=num).delete()

        return CommomResponse(msg=‘删除成功‘)

    def put(self,request,num):
        book=self.get_queryset().filter(pk=num).first()#只有一个值时一定有用.first()
        ser_obj=self.get_serializer(book,request.data)
        if ser_obj.is_valid():
            ser_obj.save()  #这是序列化器的save方法,不是queryset的
            return CommomResponse(data=ser_obj.data)
        else:
            return CommomResponse(msg=‘数据不合法‘)

2.3 基于GenericAPIView和5个视图扩展类写的接口

5个视图扩展类:直接继承object的类,这些类能自动能更具请求方式相应

ListModelMixin:获取所有数据

RetrieveModelMixin:获取一条数据

CreateModelMixin:创建

UpdateModelMixin:更新

DestroyModelMixin:删除

使用方法:在相应的请求函数下调用对应的函数,有参数的还得传参:

class Books3(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = models.Booklib.objects
    serializer_class = ser.BookModelSerializer

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


class Book3(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin):
    queryset = models.Booklib.objects
    serializer_class = ser.BookModelSerializer

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

    def put(self,request,pk):
        return self.update(request,pk)

    def delete(self,request,pk):
        return self.destroy(request,pk)

2.4 基于GenericAPIView的9个视图拓展类编写接口:

分别是:

5个基础组合类
CreateAPIView,ListAPIView,RetrieveAPIView,DestroyAPIView,UpdateAPIView 
4个扩展组合类
ListCreateAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView,RetrieveUpdateDestroyAPIView 

这9个类集合了API类和ModelMixin类的优点,同时又更进一步,类体写了请求对应的操作,继承这个类之后只需要申明操作票那个表和指定那个序列化器.

使用方法:只需要这6行代码实现面的功能

class Books4(ListCreateAPIView):
    queryset = models.Booklib.objects 
    #这里需要一个queryse对像所以要去到object
    serializer_class = ser.BookModelSerializer

class Book4(RetrieveUpdateDestroyAPIView):
    queryset = models.Booklib.objects
    serializer_class = ser.BookModelSerializer

到此为止,试图函数的代码已经大大的减少 ,但是还得自己手动配置路由路径和两个视图类的对应关系.

接下来介绍的两个类分别解决了需要写两个视图类的问提和手动配置路由匹配的问提

2.5继承ViewSetMixin的视图类

作用:只需要编写一个视图类来对应两个url

该类重写了的as_view功能匹配了请求的method和url视图层action,并且调用函数

注意:因为ViewSetMixin重写了as_view,查找as_view时会现去继承的第一父类查找,如果APIView在前则,不会执行重写的as_view导致功能失效.

当然这里的APIView也可以是GenericAPIView

class Book05(ViewSetMixin,APIView):
    def get_one_book(self,request,pk):

        obj_list = models.Booklib.objects.filter(pk=pk).first()
        ser_book = ser.BookModelSerializer(obj_list)

        return CommomResponse(data=ser_book.data)

    def get_books(self,request):
        obj_list = models.Booklib.objects.all()
        ser_book=ser.BookModelSerializer(obj_list,many=True)

        return CommomResponse(data=ser_book.data)
    
    URL写法:
   url(r‘^api/books5/$‘, views.Book05.as_view(actions=‘get‘:‘get_books‘)),
   url(r‘^api/book5/(?P<pk>d+)/‘, views.Book05.as_view(actions=‘get‘:‘get_one_book‘)),

2.6 基于ModelViewSet类编写接口

ModelViewSet的父类:

GenericViewSet 5个视图拓展类(这5个类都直接继承object)

GenericViewSet继承了GenericAPIView和ViewSetMixin(该类直接继承object)

GenericAPIView的继承关系就比较清晰了:

GenericAPIView>>>APIView>>>View>>>object

请求与函数的对应:

get-->list 获取多个

get-->retrieve 获取一个

post-->create

put-->update

delete-->delete

class Book06(ModelViewSet):
    queryset = models.Booklib.objects
    serializer_class = BookModelSerializer

    def list(self, request, *args, **kwargs):
        queryset = self.get_queryset()

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data[0:2])#此处使得获取所有数据的请求改为只获取前两个数据,这是通过重写list方法实现的

    @action([‘GET‘], False) #通过action装饰器自动生成list_3对应的url,False即不接受参数
    def list_3(self, request):
        pass

2.7 SimpleRouter类

该类写在路由层,作用为自动生成与视图类关联的路由

router=routers.SimpleRouter()
router.register(‘book‘,views.Book06)

urlpatterns+=router.urls#将自动生成的路由加入到原路由列表中

到此为止,ModelViewSet类和SimpleRouter类最终将上述的问题都解决了

pythondjangorest_framework框架两个视图基类详解(图文并茂版)(代码片段)

视图类详解视图基类APIView[基本视图类]GenericAPIView[通用视图类]关于序列化器的属性与方法get_serializer_class(self)get_serializer(self,*args,**kwargs)注意get_queryset(self)get_object(self)其它属性定义与实现视图基类APIView[基本视图类]APIView是所有DR... 查看详情

drf视图组件(代码片段)

目录一视图1.1试图配置1.2视图1.2.12个视图基类1.2.1.1APIView2.2.1.2GenericAPIView[通用视图类]get_serializer(self,args,*kwargs)1.2.25个视图扩展类1)ListModelMixin2)CreateModelMixin3)RetrieveModelMixin4)UpdateModelMixin5)DestroyMode 查看详情

drf序列化器之请求响应以及视图(代码片段)

...ttp请求处理drf除了在数据序列化部分简写代码以外,还在视图中提供了简写操作。所以在django原有的django.views.View类基础上,drf封装了多个视图子类出来提供给我们使用。DjangoRESTframwork提供的视图的主要作用:控制序列化器的执... 查看详情

drf视图家族(代码片段)

drf视图家族视图家族- 视图基类,视图工具类,工具视图类,视图集视图基类:APIView、GenericAPIView视图工具类:mixins包下的五个类(六个方法)工具视图类:generics包下的所有GenericAPIView的子类视图集:viewsets包下的类generics中... 查看详情

drf框架之视图的扩展类简介(代码片段)

...架,为我们提供的试图扩展类的使用方法即作用。在使用视图扩展类时,需要将mixins模块导入到view文件中。fromrest_frameworkimportmixins并且,在使用视图扩展类时,必须结合GenericAPIView基类一起使用。所谓,视图的扩展类,就是Generi... 查看详情

drf之过滤器详解(代码片段)

...替代吧文章部分来自https://zhuanlan.zhihu.com/p/110060840类似在视图中操作模型的filter,不过drf提供了过滤组件,只要简单配置,加上指定可以提供过滤的字段,就可以快速实现像在url后面用有名分组接收参数的效果使用filter,需要先... 查看详情

学习drf之前(代码片段)

...已经了解过CBV以及FBV什么是FBV和CBV呢~~  FBV基于函数的视图  CBV基于类的视图也就是说我们是用函数编写视图~还是类编写视图~~我们来看下两个的简单实现~~urlpatterns=[path(‘admin/‘,admin.site.urls),path(‘test_fbv‘,t 查看详情

django-rest-framework---总结(代码片段)

...与反序列化整合(重点)3.整体单改4.单与整体局部修改视图类视图类传递参数给序列化类二次封装Response类视图家族GenericAPIView基类mixins视图工具集-辅助GenericAPIView工具视图视图集GenericAPIView与APIView最为两大继承视图的区别工具... 查看详情

drf4.drf视图开发restfulapi接口(代码片段)

四种方式:函数式编程:functionbasedview类视图:classedbasedview通用类视图:genericclassedbasedviewDRF的视图集Viewsets原生DjangoFBV(Funcitonbasedview)编写,应用的views.pyimportjsonfromdjango.httpimportJsonResponsefromdjango.views.decorators.csrfimportcsrf_exemptcourse... 查看详情

0802drf视图(代码片段)

昨日回顾:1.Serializer(序列化)1.ORM对应的query_set和ORM对象转换成JSON格式的数据1.在序列化类中定义自定义的字段:SerializerMethodField在类中定义get_自定义字段名(self,obj)方法2.read_only只在显示(查询)时才会有效。2.对前端POST过来的... 查看详情

drf之视图组件(代码片段)

不断的优化我们写的程序,是每个程序员必备的技能和职业素养,也是帮助我们成长的非常重要的手段。相关知识点相关知识点一:RESTfulapi接口规范我给大家总结的REST的最重要的一句话,那就是:url用来唯一定位资源,http请求... 查看详情

drf视图(代码片段)

...建表3.admin.py文件4.根目录下urls.py--路由匹配5.bms/views.py--视图函数6.bms/modelserializers.py--自定义序列化工具四.进化版:使用自定义混合类和自定义通用类五.超级进化版:使用GenericViewSet通用类六.究极进化版:使用rest_framework帮我们封装... 查看详情

drf入门规范(代码片段)

...化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。 查看详情

drf中五大扩展类及视图集的介绍(代码片段)

五个扩展类(1)ListModelMixin列表视图扩展类,提供list(request,*args,**kwargs)方法快速实现列表视图,返回200状态码。该Mixin的list方法会对数据进行过滤和分页。源代码:classListModelMixin(object):"""Listaqueryset."""deflist(self,request,*args,**kwargs):... 查看详情

drf-视图集路由系统action装饰器(代码片段)

1.9个视图扩展类1.两个视图基类:APIView、GenricAPIView2.5个视图扩展类:CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,ListModelMixin,DestroyModelMixin3.9个视图子类:CreateAPIView,DestroyAPIView,ListAPIView,RetrieveAPIView,UpdateAPIView,ListCreateAPIView,RetrieveDestroyAPIVi... 查看详情

drf-过滤组件(代码片段)

...tPagination游标分页CursorPaginationfilter过滤类源码分析我们从视图类中群查接口入口,去看看它内部是怎么实现过滤的首先我们进入ListAPIView类中实现群查功能的是它的第一个父类mixins中调用的,我们进入它的第一个父类我们看到它... 查看详情

drf视图(代码片段)

目录开始使用内置视图请结合【DRF序列化】此文献中的数据文件及序列化文件来阅读如下代码.DRF视图为我们提供了非常简便的方法——内置了增删改查等一系列的操作.我们只需在url中指定对应的方法,视图继承内置方法的类,... 查看详情

pythondjangorest_framework框架两个视图基类详解(图文并茂版)(代码片段)

视图类详解视图基类APIView[基本视图类]GenericAPIView[通用视图类]关于序列化器的属性与方法get_serializer_class(self)get_serializer(self,*args,**kwargs)注意get_queryset(self)get_object(self)其它属性定义与实现视图基类APIView[基本视图类]APIView是所有DR... 查看详情