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系统中,不同的应用 ...
随机推荐
- 挖矿程序minerd入侵分析和解决办法
现在比特币的价格涨得很高,所以现在有黑客专门制造挖矿木马来诱导网友,从而达到控制电脑上的显卡来挖掘比特币.为什么木马要控制电脑中的显卡呢?因为显卡挖掘虚拟货币比特币的效率远比 CPU 要高.如果你是一 ...
- maven详解 之 pom.xml
Maven 一个项目管理工具 其作用就是用来管理jar 包的 maven的核心 pom.xml配置文件 <project xmlns="http://maven.apache ...
- python数据分析基础
---恢复内容开始--- Python数据分析基础(1) //2019.07.09python数据分析基础总结1.python数据分析主要使用IDE是Pycharm和Anaconda,最为常用和方便的 ...
- 【LeetCode】226. 翻转二叉树
题目 翻转一棵二叉树. 示例: 输入: 4 / \ 2 7 / \ / \ 1 3 6 9 输出: 4 / \ 7 2 / \ / \ 9 6 3 1 本题同[剑指Offer]面试题27. 二叉树的镜 ...
- UVA - 1572 Self-Assembly(图论模型+拓扑排序)
题意:判断利用给出的正方形是否能拼接出无限延伸的结构. 分析:正方形上的字母看做点,正方形看做有向边. 例如: 若上下两个正方形能拼接,需要B+~C+是个有向边. 对输入的处理是:把A+,A-分别映射 ...
- 每天一点点之vue框架学习 - uni-app 修改上一页参数
方法一:使用微信提供的 getCurrentPages() 来实现 // 更新上一级的数据 getPrevData(){ var pages = getCurrentPages(); var curr ...
- 51nod 1294 :修改数组 && HDU 5256:序列变换
1294 修改数组 题目来源: HackerRank 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 取消关注 给出一个整数数组A,你可以将任何一个数修 ...
- require(): open_basedir restriction in effect. File(/www/wwwroot/xcx/zerg/thinkphp/start.php) is not within the allowed path(s): (/www/wwwroot/xcx/zerg/public/:/tmp/:/proc/) in /www/wwwroot/xcx/zerg/p
解决方法: 在如下文件增加一项(如图所示) 在如下文件增加一项(如图所示): #php文件采用fastcgi解析并设置参数 location ~ \.php { try_files ...
- Python MySQL 创建表
章节 Python MySQL 入门 Python MySQL 创建数据库 Python MySQL 创建表 Python MySQL 插入表 Python MySQL Select Python M ...
- jupiter的@TempDir 等不生效
jupiter与junit是 完全独立的测试组件,要严防在测试中将二者混用.最好在依赖引入jupiter 时 就将junit的依赖干掉,以防在写测试用例时将二者混用.不会报错,但是会导致 jupite ...