管理器类(Manager)
django中的Manager类是我们通过模型类去操作数据库的工具,django给每个定义的模型默认添加一个名为objects的manager类的对象。django官网文档对Manager的概述如下:
` A Manager is the interface through which database query operations are provided to Django models.At least one Manager exists for every model in a Django application.
先看一个对管理器的基本使用,定义一个基本的图书信息类:
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
bpub_date = models.DateField()
bread = models.IntegerField(default=0)
bcomment = models.IntegerField(default=0)
bisDelete = models.BooleanField(default=False)
def __str__(self):
return self.btitle
接下来我们要查询BookIno中的所有图书(查询语句以及结果如下)
>>> BookInfo.objects.all()
[<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]
执行完上述查询语句之后,假设我们现在又接收到了一个客户端的请求,要求删除“雪山飞狐”这本书,执行下面的代码对数据库执行逻辑删除操作:
book = BookInfo.objects.get(btitle='雪山飞狐')
book.bisDelete = 1
book.save()
以后我们再执行查询所有图书的信息的时候,就需要去掉被删除的图书。一种做法是每次都查询出所有的图书信息然后去掉bisDelete=1的字段:
>>> BookInfo.objects.all().exclude(bisDelete=1)
[<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>]
但是我们每次操作都需要写一遍上面的代码未免太麻烦,并且我们要查询所有的图书信息时本来就默认去掉了被删除的图书的信息,而objects这个管理器类中的all方法是把所有信息都返回,显然不满足我们的要求,这个时候我们需要去自定义管理器类去重新实现all()方法。
自定义管理器类
class BookManager(models.Manager):
#重写父类的all方法
def all(self):
all_data = super().all()
return all_data.exclude(bisDelete=1)
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
bpub_date = models.DateField()
bread = models.IntegerField(default=0)
bcomment = models.IntegerField(default=0)
bisDelete = models.BooleanField(default=False)
def __str__(self):
return self.btitle
#实例化自定义管理器类(此时默认的objects管理类对象已经失效)
bmanager = BookManager()
#使用自定义管理类
>>> BookInfo.bmanager.all()
[<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>]
扩展管理类功能
前面我们通过自定义管理器类扩展了原有的all()方法,但是有的时候我们想要的功能在管理器类中不仅不具备相应的方法,甚至连类似的可继承扩展的方法都没有,这个时候我们就需要完全自定义一个方法了。比如下面的一个场景,我们不希望每次拿到的返回结果都是QuerySet类型的集合对象,我们希望每次查询返回的是一个包含满足条件的图书名的列表,这个时候我们可以在自定义管理器类中定义一个方法完全适配我们要求的方法(其实这种自定义扩展方法本质就是把对Manager管理类查询结果的过滤操作从类外面搬到了管理类内部)
class BookManager(models.Manager):
# 查询大于给定id号的图书信息
def blist(self,id):
ls = []
all_data = super().filter(id__gt=id)
for book in all_data:
ls.append(book.btitle)
return ls
#进行测试
>>> BookInfo.bmanager.blist(2)
['笑傲江湖', '雪山飞狐']