首先要知道元类是什么
python中一切皆对象,那么定义的类也是对象,而类是由什么创建的呢?
自定义一个类,在使用type()函数,可以看见这个类是type类型的,所以自定义的这个类必然是type创建的。
实际上:类是由元类创建的,当定义一个类时如果没有指定元类,就会一层层向上找,如果父类中也没有指定元类,再向上找模块,模块也没有,就会使用内置的type()来创建类。
如果指定了元类,那么就会改变这一默认行为,使用指定的元类来创建类。
所有自定义的元类都必须继承 type, 且需要重写 __ new __()方法,该方法用来创建实例
它接受四个参数:需要实例化的类对象,类的名字,类继承的父类集合,类的字典属性
可在该方法内控制类对象的生成过程。
为何要继承models.Model?
自动添加的自增主键
Model指定了元类为ModelBase(继承自type),所有自定义的Model都是由ModelBase创建出来的。ModelBase的__ new __()方法中引用了 _prepare()方法,该方法中判断了是否自定义了主键,如果没有则添加一个自增主键。
自动添加的查询管理器
Django会为每一个Model自动添加一个名称为objects的查询管理器,其实现也是在_prepare() 中。最终可知Model.objects并不是一个Manager对象,而是ManagerDescriptor实例,ManagerDescriptor是一个描述符,是对Manager访问的一种保护,主要实现对Model实例和抽象Model的拒绝访问。
利用Manager(objects)就可以实现对Model的增删改查,有些方法还会返回QuerySet,这是怎么实现的呢?
创建Model实例
返回单实例的查询方法
返回QuerySet的查询方法
Manager的all()方法,返回所有数据实例。
reverse()方法,获取全量数据,排列顺序与all相反
order_by()方法,可自定义怕徐规则,可指定多个排序字段
filter()方法,获取全量数据的一个子集,等同于使用where子句过滤不符合条件的记录
#####################
contains(), startswith(), endswith()都有对应的忽略大小写的版本,即在方法名前面添加 字母 i 就可以了
exclude()方法,反向过滤,相等于在filter前面加了一个not
链式查询由于filter,exclude这样的方法返回的是QuerySet,所以可在其后继续调用filter,exclude
values()方法获取字典结果,该方法同样会返回QuerySet,但并不是Model的实例对象,而是字典类型,字典的键对应Model的字段名
values_list()方法,和values()及其相似,只不过返回的是元组而不是字典,元组元素的顺序与传递的字段顺序相同
对QuerySet进行切片操作,例如Comment.objects.all()[:2],QuerySet不支持负值索引
返回RawQuerySet的查询方法
Djang的ORM非常强大,支持使用原生sql语句实现查询
Comment.objects.raw(‘select * from post_comment‘)
返回其他类型的查询方法
select count(*)
返回数字类型小写模型名_set
F对象查询,主要用于 操作数据库中某一列的值,可以在 没有实际访问数据库 的情况下对字段的值进行引用
F对象功能强大,支持跨关联关系。且使用F对象,可以避免线程不安全导致的脏数据。使用F对象,让数据库负责更新过程。F对象描述的是SQl表达式,而不是Python运算。
Q对象查询,用于复杂查询,将关键字封装在一起,并传递给filter,exclude,get等方法。多个Q对象可以使用 &,| 进行组合,产生一个新的Q对象。使用 ~可实现NOT查询。Q对象也可以与关键字参数组合在一起,但这种情况下,Q对象必须放在最前面。
原文:https://www.cnblogs.com/leerep/p/14645028.html