看登录中间件的时候发现request.user返回的是SimpleOject对象,往下看翻到了LazyObject,看源码看了半天没看懂

网上搜了一堆资料了解下惰性加载实现是的什么功能,再回去看源码,大概知道了LazyObject实现的原理

Django的惰性加载,就是生成对象的时候先不实例化,等到需要调用对象的属性或方法的时候再做实例化的操作

LazyObject源码:

empty = object()

#为类方法实现通用的惰性加载方法,即查看对象是否实例化
#若还未实例化,调用子类实例化方法
#最后在生成的实例上调用原来的func类方法
def new_method_proxy(func):
def inner(self, *args):
if self._wrapped is empty:
self._setup()
return func(self._wrapped, *args)
return inner class LazyObject:
"""
A wrapper for another class that can be used to delay instantiation of the
wrapped class. By subclassing, you have the opportunity to intercept and alter the
instantiation. If you don't need to do that, use SimpleLazyObject.
""" # Avoid infinite recursion when tracing __init__ (#19456).
_wrapped = None def __init__(self):
# Note: if a subclass overrides __init__(), it will likely need to
# override __copy__() and __deepcopy__() as well.
self._wrapped = empty #标记是否有实例化 __getattr__ = new_method_proxy(getattr) #调用通用的延迟实例化方法 def __setattr__(self, name, value):
if name == "_wrapped": #若修改的为_wrapped,特殊处理
# Assign to __dict__ to avoid infinite __setattr__ loops.
self.__dict__["_wrapped"] = value
else:
if self._wrapped is empty:
self._setup()
setattr(self._wrapped, name, value) #实例化后,修改实例的属性 def __delattr__(self, name):
if name == "_wrapped": #不可删除_wrapped属性
raise TypeError("can't delete _wrapped.")
if self._wrapped is empty:
self._setup()
delattr(self._wrapped, name) def _setup(self):
"""
Must be implemented by subclasses to initialize the wrapped object.
"""
#只可由子类调用
raise NotImplementedError('subclasses of LazyObject must provide a _setup() method') # Because we have messed with __class__ below, we confuse pickle as to what
# class we are pickling. We're going to have to initialize the wrapped
# object to successfully pickle it, so we might as well just pickle the
# wrapped object since they're supposed to act the same way.
#
# Unfortunately, if we try to simply act like the wrapped object, the ruse
# will break down when pickle gets our id(). Thus we end up with pickle
# thinking, in effect, that we are a distinct object from the wrapped
# object, but with the same __dict__. This can cause problems (see #25389).
#
# So instead, we define our own __reduce__ method and custom unpickler. We
# pickle the wrapped object as the unpickler's argument, so that pickle
# will pickle it normally, and then the unpickler simply returns its
# argument.
def __reduce__(self):
if self._wrapped is empty:
self._setup()
return (unpickle_lazyobject, (self._wrapped,)) def __copy__(self):
if self._wrapped is empty:
# If uninitialized, copy the wrapper. Use type(self), not
# self.__class__, because the latter is proxied.
return type(self)()
else:
# If initialized, return a copy of the wrapped object.
return copy.copy(self._wrapped) def __deepcopy__(self, memo):
if self._wrapped is empty:
# We have to use type(self), not self.__class__, because the
# latter is proxied.
result = type(self)()
memo[id(self)] = result
return result
return copy.deepcopy(self._wrapped, memo) __bytes__ = new_method_proxy(bytes)
__str__ = new_method_proxy(str)
__bool__ = new_method_proxy(bool) # Introspection support
__dir__ = new_method_proxy(dir) # Need to pretend to be the wrapped class, for the sake of objects that
# care about this (especially in equality tests)
__class__ = property(new_method_proxy(operator.attrgetter("__class__")))
__eq__ = new_method_proxy(operator.eq)
__lt__ = new_method_proxy(operator.lt)
__gt__ = new_method_proxy(operator.gt)
__ne__ = new_method_proxy(operator.ne)
__hash__ = new_method_proxy(hash) # List/Tuple/Dictionary methods support
__getitem__ = new_method_proxy(operator.getitem)
__setitem__ = new_method_proxy(operator.setitem)
__delitem__ = new_method_proxy(operator.delitem)
__iter__ = new_method_proxy(iter)
__len__ = new_method_proxy(len)
__contains__ = new_method_proxy(operator.contains)

Django惰性加载和LazyObject的更多相关文章

  1. PDF在线阅读 FlexPaper 惰性加载 ;

    关于PDF在线阅读问题,比较普遍的做法是转换成swf文件来浏览:由于项目需要,就用 flexpaper 来实现了下,功能比较简单:但是文件的惰性加载确实让笔者挠头了一把! 下面是笔者的方法: 采用流的 ...

  2. Angular2 ng2 如何配置惰性加载

    需要修改至少四个地方1. 将子组件进行模块化操作2.生成子组件module .子组件router3.配置主路由 信息 改为loadChild4.配置appModule 删除引入 以product组件 ...

  3. 雷林鹏分享:jQuery EasyUI 树形菜单 - 树形网格惰性加载节点

    jQuery EasyUI 树形菜单 - 树形网格惰性加载节点 有时我们已经得到充分的分层树形网格(TreeGrid)的数据. 我们还想让树形网格(TreeGrid)按层次惰性加载节点. 首先,只加载 ...

  4. angular惰性加载拓展剖析

    最近把一个比较旧的业余项目重新升级了下,将主文件进行了剥离,增加了些惰性加载的配置,将过程中一些零散的知识点做个总结,同时尽量深入原理实现层面. 项目环境: 前端框架:angular2.0.0-bet ...

  5. 关于angular5的惰性加载报错问题

    之前为了测试一个模块优化问题,于是用angular-cli快速搭建了个ng5的脚手架demo,在应用惰性加载功能的时候发现浏览器报错如下: ERROR Error: Uncaught (in prom ...

  6. Angular惰性加载的特性模块

    一:Angular-CLI建立应用 cmd命令:ng new lazy-app --routing    (创建一个名叫 lazy-app 的应用,而 --routing 标识生成了一个名叫 app- ...

  7. django如何加载外部文件

    django如何加载外部文件(环境:pycharm python2.7 django1.11) 有一份新的文件夹名为:py_aiplat_demo,内含有多个文件夹(SDK,demo,data). 1 ...

  8. javascript 性能惰性加载2016.12.13

    利用函数的惰性载入提高 javascript 代码性能 原文:利用函数的惰性载入提高javascript代码性能 作者:阿安 在 javascript 代码中,因为各浏览器之间的行为的差异,我们经常会 ...

  9. django无法加载admin的静态内容的问题(Centos7+Nginx+uwsgi环境下)

    Nginx静态资源无法加载,导致admin没有CSS样式: 这个问题,主要是要理解: 1.Django不会去解析静态内容(css,js,img)等,而是交给Nginx去处理,所以nginx.conf要 ...

随机推荐

  1. day18 函数定义、参数;名称空间;全局变量及局部变量。

    Python之路,Day6 = Python基础6 函数的定义 def func1(): # 定义一个函数,名字叫func1,括号中没有传入参数 print('hello word') # 这里是 f ...

  2. php设置时区和strtotime转化为时间戳函数

    date_default_timezone_set('PRC');//设置中华人民共和国标准时间 strtotime — 将任何英文文本的日期时间描述解析为 Unix 时间戳 格式:int strto ...

  3. 关于Async与Await的FAQ

    =============C#.Net 篇目录============== 环境:VS2012(尽管System.Threading.Tasks在.net4.0就引入,在.net4.5中为其增加了更丰 ...

  4. chattr和lsattr命令,不能被删除、改名、设定链接关系,同时不能写入或新增内容

    chattr和lsattr命令详解 chattr命令的作用很大,其中一些功能是由Linux内核版本来支持的,如果Linux内核版本低于2.2,那么许多功能不能实现.同样-D检查压缩文件中的错误的功能, ...

  5. 响应式编程(Reactive Programming)(Rx)介绍

    很明显你是有兴趣学习这种被称作响应式编程的新技术才来看这篇文章的. 学习响应式编程是很困难的一个过程,特别是在缺乏优秀资料的前提下.刚开始学习时,我试过去找一些教程,并找到了为数不多的实用教程,但是它 ...

  6. dockerfile自动创建docker镜像

    特点:类似于ansible 剧本,大小几kb 而,手动做的镜像,要几百M,甚至上G ,传输不方便 dockerfile 支持自定义容器的初始命令 dockerfile只要组成部分: 基础镜像信息 FR ...

  7. 在core2.0中实现按程序集注入依赖

    前言:在Autofac的使用中,提供了个种注入的API其中GetAssemblies()用着特别的舒坦. 1.core2.0也可以使用Autofac的包,但框架自身也提供了默认的注入Api,IServ ...

  8. shell脚本练习03--字符串

    ######################################################################### # File Name: -.sh # Author ...

  9. [WPF自定义控件库] 让Form在加载后自动获得焦点

    原文:[WPF自定义控件库] 让Form在加载后自动获得焦点 1. 需求 加载后让第一个输入框或者焦点是个很基本的功能,典型的如"登录"对话框.一般来说"登录" ...

  10. java笔试之求最大连续bit数

    功能: 求一个byte数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1    输入: 一个byte型的数字    输出: 无     返回: 对应的二进制数字中1 ...