78.objects对象所属类原理分析
def index3(request):
# 查找文章题目中包含中国的文章分类
category = Category.objects.filter(article__title__contains='中国')
print(type(Category.objects))
print(type(category))
# print(category.query)
return HttpResponse("success!")
返回的结果为:
<class 'django.db.models.manager.Manager'>
<class 'django.db.models.query.QuerySet'>
1. 由打印的结果我们可以看出,type(Category.objects)的类型为Manager。因此,我们可以将鼠标放在objects上按ctrl+b(或者是从from django.db.models.manager import Manager,将鼠标放在Manager上按ctrl+b),进入Manager类。
class Manager(BaseManager.from_queryset(QuerySet)):
pass
2.进入之后我们会发现其实Manager类为一个空的类,并没有定义的方法或是属性。但是它继承了父类BaseManager的类方法from_queryset(),from_queryset()中传递了一个QuerySet类名。
3. 接着我们将鼠标放在from_queryset()方法上,ctrl+b,查看from_queryset()方法是怎么实现的?
# 在这里没有写明BaseManager是继承了哪个类,默认情况下就是继承了objects。即为class BaseManager(objects):
class BaseManager:
@classmethod
# 传进来的参数cls代表的是当前的类名BaseManager,
# queryset_class:代表的是from_queryset()接收的值QuerySet,而class_name为默认值None
def from_queryset(cls, queryset_class, class_name=None):
# 因为我们的from_queryset()方法只接受一个参数,所以class_name为None,满足if条件
if class_name is None:
# class_name=BaseManagerFromQuerySet
class_name = '%sFrom%s' % (cls.__name__, queryset_class.__name__)
# type()函数可以用来动态创建类:返回type(创建的类名:BaseManagerFromQuerySet,继承的类:可以是单继承也可以是多继承,用元组表示:(cls,), class_dict)
# class_dict:{
# '_queryset_class': QuerySet,
# **cls._get_queryset_methods(QuerySet):代表的是调用当前类BaseManager的_get_queryset_methods()方法所得到的返回值。同样我们可以将鼠标放在_get_queryset_methods()方法上,ctrl+b查看方法的返回值。
}
return type(class_name, (cls,), {
'_queryset_class': queryset_class,
**cls._get_queryset_methods(queryset_class),
})
4. **cls._get_queryset_methods(queryset_class)相关说明:
class BaseManager:
@classmethod
def _get_queryset_methods(cls, queryset_class):
# create_method()方法中传递两个参数name和method,返回的是manager_method,
def create_method(name, method):
def manager_method(self, *args, **kwargs):
return getattr(self.get_queryset(), name)(*args, **kwargs)
manager_method.__name__ = method.__name__
manager_method.__doc__ = method.__doc__
return manager_method
# 定义一个新的方法字典
new_methods = {}
# 遍历QuerySet的函数,找到name和method
for name, method in inspect.getmembers(queryset_class, predicate=inspect.isfunction):
# Only copy missing methods.
# hasattr(cls,name)返回的对象是否具有给定名称的属性,如果返回值为True就继续以下操作
if hasattr(cls, name):
continue
# 拷贝公共的方法或者是属性queryset_only=False的方法。
# Only copy public methods or methods with the attribute `queryset_only=False`.
queryset_only = getattr(method, 'queryset_only', None)
if queryset_only or (queryset_only is None and name.startswith('_')):
continue
# Copy the method onto the manager.
# 在这里我们可以将鼠标放在create_method()方法上,ctrl+b,查看该方法执行的操作:返回了一个manager_method(manager方法名)被赋值给new_methods
new_methods[name] = create_method(name, method)
# 将拷贝的多个函数都返回给new_methods,并且返回new_methods.
# 此时的_get_queryset_methods(QuerySet)的返回值就是拷贝的多个QuerySet的方法。
return new_methods
5. 因此,我们的from_queryset()方法返回的return type(class_name, (cls,), { '_queryset_class': queryset_class, **cls._get_queryset_methods(queryset_class),})中 **cls._get_queryset_methods(queryset_class)的值为:
# class_dict:{
# '_queryset_class': QuerySet,
# **cls._get_queryset_methods(QuerySet):得到拷贝的QuerySet的多个方法
# }
6. 因此我们from_queryset(QuerySet)就拷贝到了QuerySet的多个方法,而我们的空类Manager因为继承了BaseManager.from_queryset(QuerySet)也就有了QuerySet很多的方法。所以我们可以在模型名.objects上就可以调用很多QuerySet的方法。
class Manager(BaseManager.from_queryset(QuerySet)):
pass
78.objects对象所属类原理分析的更多相关文章
- String类原理分析及部分方法
//String类原理分析及部分方法 //http://www.cnblogs.com/vamei/archive/2013/04/08/3000914.html //http://www.cnblo ...
- ThreadLocalRandom类原理分析
1.Random类及其局限性 public int nextInt(int bound) { if (bound <= 0) throw new IllegalArgumentException ...
- Cocos2d-X3.0 刨根问底(五)----- Node类及显示对象列表源码分析
上一章 我们分析了Cocos2d-x的内存管理,主要解剖了 Ref.PoolManager.AutoreleasePool这三个类,了解了对象是如何自动释放的机制.之前有一个类 Node经常出现在各种 ...
- Junit 注解 类加载器 .动态代理 jdbc 连接池 DButils 事务 Arraylist Linklist hashset 异常 哈希表的数据结构,存储过程 Map Object String Stringbufere File类 文件过滤器_原理分析 flush方法和close方法 序列号冲突问题
Junit 注解 3).其它注意事项: 1).@Test运行的方法,不能有形参: 2).@Test运行的方法,不能有返回值: 3).@Test运行的方法,不能是静态方法: 4).在一个类中,可以同时定 ...
- 关于boost中enable_shared_from_this类的原理分析
首先要说明的一个问题是:如何安全地将this指针返回给调用者.一般来说,我们不能直接将this指针返回.想象这样的情况,该函数将this指针返回到外部某个变量保存,然后这个对象自身已经析构了,但外部变 ...
- String类中intern方法的原理分析
一,前言 昨天简单整理了JVM内存分配和String类常用方法,遇到了String中的intern()方法.本来想一并总结起来,但是intern方法还涉及到JDK版本的问题,内容也相对较多,所以今 ...
- 老李推荐:第6章3节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令翻译类
老李推荐:第6章3节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令翻译类 每个来自网络的字串命令都需要进行解析执行,只是有些是在解析的过程中直接执行 ...
- Java编译时根据调用该方法的类或对象所属的类决定
class Base{ int x = 1; static int y = 2; } class Subclass extends Base{ int x = 4; i ...
- Android应用程序组件Content Provider在应用程序之间共享数据的原理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6967204 在Android系统中,不同的应用 ...
随机推荐
- R 正态性检验:正态概率图
检验模型是否满足正态性假设的方法: 1.正态概率图 这是我编写的画正态概率图的函数: #绘制正态概率图 plot_ZP = function(ti) #输入外部学生化残差 { n = length(t ...
- windows下 RN 环境搭建
01.安装 Android Studio 02.NodeJs 03.Python204.JDK 05.安装Genymotion模拟器06.java 环境配置07.andriud sdk 配置08.An ...
- ip 在网络传输中是如何传递的
前言 ip 我们知道有ip4与ip6.ip6还未实行,那么就暂且不谈. ip4我们在传递的时候一般是这样的"127.0.0.1",但是我们传输的是信号,也就是二进制数据,这个字符如 ...
- 018、MySQL取满足日期在两个日期之间的所有数据
#查询 SELECT GZJK_CREATEDATE FROM abc_table WHERE ( ( GZJK_CREATEDATE >= UNIX_TIMESTAMP( '2019-08-0 ...
- python二维图像输出操作大全(非常全)!
//2019.07.141.matplotlib模块输出函数图像应用时主要用的是它的ptplot模块,因此在导入使用该模块时可以直接用以下语句:import matplotlib.pyplot as ...
- ubuntu 中加速pip指令下载插件的速度
在使用pip下载时很多时候下载速度特别慢,时不时就会发生timeout. 这是因为安装源与本机之间网络不畅导致,其实可以自己指定pip的下载来源,就像指定ubuntu更新源那样. 接下来谈谈步骤: 1 ...
- SQLmap自动注入工具命令(10.28 10.29 第二十八 二十九天)
SQL注入工具:明小子 啊D 萝卜头 sqlmap 等等 SQLMAP:开源的自动化诸如利用工具,支持的数据库有12中,在/plugins中可以看到支持的数据库种类,在所有注入利用工具中他 ...
- OI生涯回顾
OI回忆录只是一个预告,估计等2020高考结束才放出来吧. 先写一下自己简单的OI历程吧: 小升初刚起步 初一 第一次比赛,NOIP PJ组215分,踩线1=,全省rk86,全国rk677(毕竟AH ...
- C++编程学习(九)this指针&友元函数
mooc西工大魏英老师的课程通道关闭了,难受.现在边看工程代码边重温刷第一遍C++时候的知识点,顺序没有按照大纲的来,想到哪写到哪. this是干啥用的? 简介:在 C++ 中,每一个对象都能通过 t ...
- python之os.exec*族用法简结
os.exec*族主要用来代替当前进程,执行新的程序,不返回值.在UNIX上,新的执行程序加载到当前进程,与调用它的进程有相同的id. os.execl(path, arg0, arg1, ...) ...