Django的rest_framework的视图之Mixin类编写视图源码解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Django的rest_framework的视图之Mixin类编写视图源码解析 Mixin类编写视图 我们这里用auther表来做演示,先为auther和autherdetail写2个url 1 2 url(r'^autherdetail/(?P\d+)', views.

Django的rest_framework的视图之Mixin类编写视图源码解析

Mixin类编写视图

我们这里用auther表来做演示,先为auther和autherdetail写2个url

1
2
url(r '^autherdetail/(?P<id>\d+)' , views.Book_detail_cbv.as_view(), name = "autherdetail" ),
url(r '^auther/' , views.Book_cbv.as_view(),name = "auther" ),  

 

然后分别为这2个类写对应的序列化的类

1
2
3
4
class  authermodelserializer(serializers.ModelSerializer):
     class  Meta:
         model  =  models.Auther
         fields  =  "__all__"

 

下面我们开写视图函数  

需要在view文件中导入2个模块

1
2
from  rest_framework  import  mixins
from  rest_framework  import  generics

 

先介绍一下mixins类,我们主要用mixins类来对queryset对象或者model对象做操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mixins.ListModelMixin
 
这个是用来显示queryset的数据
 
mixins.CreateModelMixin
 
这个用来创建一条model对象
 
mixins.RetrieveModelMixin
 
这个是用来显示一个model对象
 
mixins.DestroyModelMixin
 
这个是用来删除一个model对象
 
mixins.UpdateModelMixin
 
这个是用来更新一个model对象

  

下面我们一个一个来看下面的类

1、看下mixins.ListModelMixin

这个类就只有一个方法,list方法,我们看下面的代码其实很熟悉,就是把一个queryset对象做序列化后,然后把序列化后的结果返回

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

  

我们这里看到get_serializer中的参数有个queryset,那么这个queryset是什么呢?

 

 

 通过上面的图,我们大致可以猜到,是由self.get_queryset()这个方法返回的结果,那么这个方法又干了什么呢?

首先我们要清楚self是什么?

 

 从上面的图我们知道,self其实就是Auther_view这个类的实例对象,这个实例对象根本就没有get_queryset这个方法,但是由于这个类继承了3个类,我们一个一个找,最终在

generics.GenericAPIView这个类中找到了get_queryset这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def  get_queryset( self ):
     """
     Get the list of items for this view.
     This must be an iterable, and may be a queryset.
     Defaults to using `self.queryset`.
 
     This method should always be used rather than accessing `self.queryset`
     directly, as `self.queryset` gets evaluated only once, and those results
     are cached for all subsequent requests.
 
     You may want to override this if you need to provide different
     querysets depending on the incoming request.
 
     (Eg. return a list of items that is specific to the user)
     """
     assert  self .queryset  is  not  None , (
         "'%s' should either include a `queryset` attribute, "
         "or override the `get_queryset()` method."
         %  self .__class__.__name__
     )
 
     queryset  =  self .queryset
     if  isinstance (queryset, QuerySet):
         # Ensure queryset is re-evaluated on each request.
         queryset  =  queryset. all ()
     return  queryset

  

我们可以很清晰的看到get_queryset这个方法返回的结果就是self.queryset

那么self.queryset这个是什么呢?

我们在Auhter_view这个类中已经定义了这个类变量,所以我们这里定义的2个类变量的名称是固定的,不能随意修改的,属于配置项

 

 下面我们走的流程就和之前差不多了

先定义get请求的处理的函数

 

因为mixins.ListModelMixin这个类是为了显示queryset对象的类,那么下面我们进入这个类

 

 所以我们在get方法中,直接调用list方法的返回结果就是我们想要的结果

 

 

2、在来看mixin.CreateModelMixin类

这个类是为了创建一个model对象

首先进入这个类,看下具体的代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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  {}

  

下面我们来分析一下代码

 

首先这里有个self.get_serializer方法,这个方法也在generics.GenericAPIView类中

下面我们在来看下get_serializer方法

1
2
3
4
5
6
7
8
def  get_serializer( self * args,  * * kwargs):
     """
     Return the serializer instance that should be used for validating and
     deserializing input, and for serializing output.
     """
     serializer_class  =  self .get_serializer_class()
     kwargs[ 'context' =  self .get_serializer_context()
     return  serializer_class( * args,  * * kwargs)

  

 

 我们在来看下get_serializer_class这个方法

 

 我们看到非常清楚,这个函数的返回值就是我们先前定义个serializer_class的类变量,所以这个类变量的名称也不能修改,必须要这么写,属于一个配置类的变量

 

 流程我们已经梳理清楚了,下面我们在看下post请求的视图函数

 

 post请求调用的mixins.CreateModelMixin类中的create方法

1
2
3
4
5
6
7
8
9
10
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)

  

 

 最后我们在看下perform.create这个方法,是不是很熟悉了,调用save方法保存

 

 3、然后来看下mixins.RetriveModelMixin类

先看下这个类的代码

1
2
3
4
5
6
7
8
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)

  

然后在来看下get_object这个方法干了什么,这个方法同样在generics.GenericAPIView类中,我们一猜就知道这个方法是获取一个model对象,然后对这个model对象进行序列化处理

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def  get_object( self ):
     """
     Returns the object the view is displaying.
 
     You may want to override this if you need to provide non-standard
     queryset lookups.  Eg if objects are referenced using multiple
     keyword arguments in the url conf.
     """
     queryset  =  self .filter_queryset( self .get_queryset())
 
     # Perform the lookup filtering.
     lookup_url_kwarg  =  self .lookup_url_kwarg  or  self .lookup_field
 
     assert  lookup_url_kwarg  in  self .kwargs, (
         'Expected view %s to be called with a URL keyword argument '
         'named "%s". Fix your URL conf, or set the `.lookup_field` '
         'attribute on the view correctly.'  %
         ( self .__class__.__name__, lookup_url_kwarg)
     )
 
     filter_kwargs  =  { self .lookup_field:  self .kwargs[lookup_url_kwarg]}
     obj  =  get_object_or_404(queryset,  * * filter_kwargs)
 
     # May raise a permission denied
     self .check_object_permissions( self .request, obj)
 
     return  obj

  

我们看到这个方法确实返回一个obj对象

 

 

 

 

最后看下get请求,调用mixins。RetrieveModelMixin类中的retieve方法返回我们要查询的结果

 

 4、然后我们在看下mixins.DestroyModelMixin类

 直接拿到model独享,然后调用perform_destory方法删除这个model对象

1
2
3
4
5
6
7
8
9
10
11
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()

  

然后我们在看下视图函数中是如何处理delete请求的

1
2
3
4
5
6
7
8
9
class  Autherdetail_view(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView):
     queryset  =  models.Auther.objects. all ()
     serializer_class  =  authermodelserializer
 
     def  get( self ,request, * args, * * kwargs):
         return  self .retrieve(request, * args, * * kwargs)
 
     def  delete( self ,request, * args, * * kwargs):
         return  self .destroy(request, * args, * * kwargs)

  

直接返回mixins.DestoryModelMixins的detory函数的返回值就可以了

 

 

5、最后看下mixins.UpdateModelMixin类

同样,先获取model对象,然后获取序列化类,然后把model对象和request.data一起传递给序列化类

序列化类在调用调用sava方法保存数据 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)

  

 

 

 

我们在看put请求的视图函数

1
2
3
4
5
6
7
8
9
10
11
12
class  Autherdetail_view(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView):
     queryset  =  models.Auther.objects. all ()
     serializer_class  =  authermodelserializer
 
     def  get( self ,request, * args, * * kwargs):
         return  self .retrieve(request, * args, * * kwargs)
 
     def  delete( self ,request, * args, * * kwargs):
         return  self .destroy(request, * args, * * kwargs)
 
     def  put( self ,request, * args, * * kwargs):
         return  self .update(request, * args, * * kwargs)

  

 

原文地址https://www.cnblogs.com/bainianminguo/p/10463741.html

相关文章
|
15天前
|
存储 Java API
详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
【10月更文挑战第19天】深入剖析Java Map:不仅是高效存储键值对的数据结构,更是展现设计艺术的典范。本文从基本概念、设计艺术和使用技巧三个方面,详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
35 3
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
28 3
|
1月前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
43 3
|
30天前
|
程序员 开发者 Python
深度解析Python中的元编程:从装饰器到自定义类创建工具
【10月更文挑战第5天】在现代软件开发中,元编程是一种高级技术,它允许程序员编写能够生成或修改其他程序的代码。这使得开发者可以更灵活地控制和扩展他们的应用逻辑。Python作为一种动态类型语言,提供了丰富的元编程特性,如装饰器、元类以及动态函数和类的创建等。本文将深入探讨这些特性,并通过具体的代码示例来展示如何有效地利用它们。
32 0
|
3月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
42 0
Spring高手之路22——AOP切面类的封装与解析
|
2月前
|
数据处理 Python
Django视图:构建动态Web页面的核心技术
Django视图:构建动态Web页面的核心技术
|
3月前
|
开发者 编解码
界面适应奥秘:从自适应布局到图片管理,Xamarin响应式设计全解析
【8月更文挑战第31天】在 Xamarin 的世界里,构建灵活且适应性强的界面是每位开发者的必修课。本文将带您探索 Xamarin 的响应式设计技巧,包括自适应布局、设备服务协商和高效图片管理,帮助您的应用在各种设备上表现出色。通过 Grid 和 StackLayout 实现弹性空间分配,利用 Device 类检测设备类型以加载最优布局,以及使用 Image 控件自动选择合适图片资源,让您轻松应对不同屏幕尺寸的挑战。掌握这些技巧,让您的应用在多变的市场中持续领先。
37 0
|
3月前
|
C++ Python
Django视图函数VS类视图:如何选择最适合你的开发方式?
【8月更文挑战第31天】本文对比了Django中的函数视图和类视图。函数视图直接处理HTTP请求和响应,灵活且易于维护,适用于简单业务逻辑;类视图基于Python类,提供更丰富的功能和更高的灵活性,适合处理复杂业务逻辑。选择哪种视图取决于具体需求,合理使用两者可帮助你构建高效且易维护的Django应用。
54 0
|
3月前
|
存储 开发者 Ruby
【揭秘Ruby高手秘籍】OOP编程精髓全解析:玩转类、继承与多态,成就编程大师之路!
【8月更文挑战第31天】面向对象编程(OOP)是通过“对象”来设计软件的编程范式。Ruby作为一种纯面向对象的语言,几乎所有事物都是对象。本文通过具体代码示例介绍了Ruby中OOP的核心概念,包括类与对象、继承、封装、多态及模块混合,展示了如何利用这些技术更好地组织和扩展代码。例如,通过定义类、继承关系及私有方法,可以创建具有特定行为的对象,并实现灵活的方法重写和功能扩展。掌握这些概念有助于提升代码质量和可维护性。
34 0
|
3月前
|
Linux Shell 数据库
python Django教程 之 安装、基本命令、视图与网站
python Django教程 之 安装、基本命令、视图与网站

推荐镜像

更多