Django自定义管理器

Django为每个模型自动添加的objects属性是一个Manager对象,用于管理模型实例。Manager由元类ModelBase创建,提供如filter()、aggregate()等方法。通过覆盖Manager的get_queryset()方法可自定义管理器,实现特定查询逻辑,例如在逻辑删除场景中过滤已删除数据。Manager本质上是QuerySet的扩展,方便对数据库进行操作。
摘要由CSDN通过智能技术生成
  • objects

对于Django中的每一个模型,django都会添加一个objects属性,这个属性就是一个管理这个模型的Manager对象。

比如:我们创建一个模型Book

20190108231338776.png

 打印Book的objects属性,并打印其类型

20190108231608398.png

结果:

20190108231643814.png

可以明显的看到objects是Book模型的一个属性,是Django的Manager模型管理器的一个对象。

  • 我们定义模型的时候并没有定义这个属性,这个属性什么时候创建的呢?

是在定义模型的时候由Django为我们创建的。在定义模型的时候必须继承models.Model类,只有继承了这个类之后,该类才能算是Django模型。看看Model类

20190109094648316.png

它由继承自由meta class(元类)ModelBase创建出来的类。那看看ModelBase

2019010909501942.png

可以看到ModelBase是所有model的metaclass。在ModelBase的__new__方法(用于创建该类对象)最后有这个方法调用:

2019010910003813.png

那看看这个方法:

20190109100143312.png

这个类为创建ModelBase实例做出了预前操作,在这个方法的最后:

20190109100837978.png

为这个ModelBase实例添加了objects属性,这个属性就是一个Manager对象。

总结:objects是由metaclass(元类)BaseModel创建的,所有由BaseModel创建的类都包括objects属性,它是一个Manager对象(模型管理器)。Model继承自由BaseModel创建的对象,而我们创建的模型都继承自Model,所以我们创建的模型都包括了objects属性,也就是每个模型的管理器Manager。

  • Manager

我们按住Ctrl键左键点击进入objects时,都会直接跳转到Manager。因为它是由元类BaseModel创建的属性,并不是直接声明的类属性,所以会直接跳转到Manager.

20190109102801655.png

2019010910281842.png

可以看到Manager继承自BaseManager的from_queryset(QuerySet)所创建的类对象。看看这个方法

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDI3ODUxMg==,size_16,color_FFFFFF,t_70

cls :BaseManager类对象

queryset_class:QuerySet类对象

 class_name:要创建的类的名字

可以看到这个方法返回了一个继承自BaseManager的类对象。在返回之前更新了类字典(新创建类的成员,成员由QuerySet类对象而来。)

接着看看_get_queryset_methods()

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDI3ODUxMg==,size_16,color_FFFFFF,t_70

是一个多层嵌套函数,在最底层的函数调用了get_queryset()方法。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDI3ODUxMg==,size_16,color_FFFFFF,t_70

 接着它将QuerySet中所有的可以被外部使用,并且在BaseManager中没有被定义的方法拷贝(更新)到类字典中。所以我们由BaseManager创建的 所有类都有了QuerySet类中的所有公开方法。这些方法就是我们管理器可以调用的方法(比如filter()、arrgerate()、get()、last()、first()……)。objects是一个Manager对象,Manager继承自BaseManager,所以objects都可以调用这些方法。

再回去看get_queryset()方法

20190109130829247.png

可以看到它它返回了一个QuerySet对象。

20190109142818306.png

QuerySet表示一组对象的延迟数据库查找。

最重要的是子类覆盖掉此方法可以很轻松的完成自定义管理器Manager的功能。这个时候我们就可以写自定义管理器了。

总结:Manager为我们创建model的管理器,它里面包括了我们模型可以通过管理器所有可以操作的方法,我们可以自定义管理器并重写get_queryset()方法来自定义我们的管理器。(可以认为管理器就是一个QuerySet的派生类)

  • 自定义管理器

objects是由ModelBase为我们创建的每一个model的属性,这个属性做为我们的model的管理器来使用。

通过覆盖管理器Manager中的get_queryset()方法可以自定义我们的管理器。如下:

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDI3ODUxMg==,size_16,color_FFFFFF,t_70

第一步:为我们的model指定管理器对象(模型的属性)

第二部:创建我们的管理器 (一个Manager类对象),继承自models.Manager.

第三部:覆盖get_queryset()方法,实现自定定义管理器。

这是时候我们的自定义管理器就创建好了。

以前我们使用的是objects管理器,当指定了管理器之后,ojects将失效。以后使用管理器就是manager了。

20190109151659291.png

这个取缔过程是由Django做的。通过迁移文件,完成模型和数据库的ORM(Object Relational Mapping,对象关系映射),并对该模型进行管理设置:

 

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDI3ODUxMg==,size_16,color_FFFFFF,t_70

可以看到迁移文件中指定了完成ORM的属性以及我们自定义的信息。

  • 使用场景

生产环境中,数据是非常重要的,删除数据经常的是逻辑删除(设置是否删除字段),而不是物理删除。而我们使用自带的管理器objects查询到的结果集通常是整张表的数据,而这不是我们想要的。而我们想要的是没有进行逻辑删除的数据,所以可以自定义管理器,实现对管理器结果的初步过滤,这样就避免了我们在使用objects默认管理器时额外的操作(每次进行数据过滤都需要先过滤没有逻辑删除的数据)。在管理器中我们也可以重写其他方法完成自定义的功能。

实际上可以认为管理器就是操作mysql的一个cursor(游标对象),而我们通过管理器调用的一些列方法相当于通过游标对象执行的sql语句。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值