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

简介: 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

相关文章
|
Java 开发者
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
490 0
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1258 29
|
存储 监控 安全
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
577 5
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
518 4
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
442 1
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
2061 12
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
531 5

推荐镜像

更多
  • DNS