详解Python的Django框架中Manager方法的使用


Posted in Python onJuly 21, 2015

在语句Book.objects.all()中,objects是一个特殊的属性,需要通过它查询数据库。 在第5章,我们只是简要地说这是模块的manager 。现在是时候深入了解managers是什么和如何使用了。

总之,模块manager是一个对象,Django模块通过它进行数据库查询。 每个Django模块至少有一个manager,你可以创建自定义manager以定制数据库访问。

下面是你创建自定义manager的两个原因: 增加额外的manager方法,和/或修manager返回的初始QuerySet。
增加额外的Manager方法

增加额外的manager方法是为模块添加表级功能的首选办法。

例如,我们为Book模型定义了一个title_count()方法,它需要一个关键字,返回包含这个关键字的书的数量。 (这个例子有点牵强,不过它可以说明managers如何工作。)

# models.py

from django.db import models

# ... Author and Publisher models here ...

**class BookManager(models.Manager):**
  **def title_count(self, keyword):**
    **return self.filter(title__icontains=keyword).count()**

class Book(models.Model):
  title = models.CharField(max_length=100)
  authors = models.ManyToManyField(Author)
  publisher = models.ForeignKey(Publisher)
  publication_date = models.DateField()
  num_pages = models.IntegerField(blank=True, null=True)
  **objects = BookManager()**

  def __unicode__(self):
    return self.title

有了这个manager,我们现在可以这样做:

>>> Book.objects.title_count('django')
4
>>> Book.objects.title_count('python')
18

下面是编码该注意的一些地方:

  •     我们建立了一个BookManager类,它继承了django.db.models.Manager。这个类只有一个title_count()方法,用来做统计。 注意,这个方法使用了self.filter(),此处self指manager本身。
  •     我们把BookManager()赋值给模型的objects属性。 它将取代模型的默认manager(objects)如果我们没有特别定义,它将会被自动创建。 我们把它命名为objects,这是为了与自动创建的manager保持一致。

为什么我们要添加一个title_count()方法呢?是为了将经常使用的查询进行封装,这样我们就不必重复编码了。
修改初始Manager QuerySets

manager的基本QuerySet返回系统中的所有对象。 例如,`` Book.objects.all()`` 返回数据库book中的所有书本。

我们可以通过覆盖Manager.get_query_set()方法来重写manager的基本QuerySet。 get_query_set()按照你的要求返回一个QuerySet。

例如,下面的模型有* 两个* manager。一个返回所有对像,另一个只返回作者是Roald Dahl的书。

from django.db import models

**# First, define the Manager subclass.**
**class DahlBookManager(models.Manager):**
  **def get_query_set(self):**
    **return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')**

**# Then hook it into the Book model explicitly.**
class Book(models.Model):
  title = models.CharField(max_length=100)
  author = models.CharField(max_length=50)
  # ...

  **objects = models.Manager() # The default manager.**
  **dahl_objects = DahlBookManager() # The Dahl-specific manager.**

在这个示例模型中,Book.objects.all()返回了数据库中的所有书本,而Book.dahl_objects.all()只返回了一本. 注意我们明确地将objects设置成manager的实例,因为如果我们不这么做,那么唯一可用的manager就将是dah1_objects。

当然,由于get_query_set()返回的是一个QuerySet对象,所以我们可以使用filter(),exclude()和其他一切QuerySet的方法。 像这些语法都是正确的:

Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()

这个例子也指出了其他有趣的技术: 在同一个模型中使用多个manager。 只要你愿意,你可以为你的模型添加多个manager()实例。 这是一个为模型添加通用滤器的简单方法。

例如:

class MaleManager(models.Manager):
  def get_query_set(self):
    return super(MaleManager, self).get_query_set().filter(sex='M')

class FemaleManager(models.Manager):
  def get_query_set(self):
    return super(FemaleManager, self).get_query_set().filter(sex='F')

class Person(models.Model):
  first_name = models.CharField(max_length=50)
  last_name = models.CharField(max_length=50)
  sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
  people = models.Manager()
  men = MaleManager()
  women = FemaleManager()

这个例子允许你执行`` Person.men.all()`` ,`` Person.women.all()`` ,`` Person.people.all()`` 查询,生成你想要的结果。

如果你使用自定义的Manager对象,请注意,Django遇到的第一个Manager(以它在模型中被定义的位置为准)会有一个特殊状态。 Django将会把第一个Manager 定义为默认Manager ,Django的许多部分(但是不包括admin应用)将会明确地为模型使用这个manager。 结论是,你应该小心地选择你的默认manager。因为覆盖get_query_set() 了,你可能接受到一个无用的返回对像,你必须避免这种情况。

Python 相关文章推荐
使用SAE部署Python运行环境的教程
May 05 Python
教你用一行Python代码实现并行任务(附代码)
Feb 02 Python
Python3爬虫之urllib携带cookie爬取网页的方法
Dec 28 Python
python使用turtle绘制国际象棋棋盘
May 23 Python
pytorch numpy list类型之间的相互转换实例
Aug 18 Python
python dataframe NaN处理方式
Dec 26 Python
Django如何使用jwt获取用户信息
Apr 21 Python
全网首秀之Pycharm十大实用技巧(推荐)
Apr 27 Python
python利用os模块编写文件复制功能——copy()函数用法
Jul 13 Python
解决Pytorch修改预训练模型时遇到key不匹配的情况
Jun 05 Python
Python实现Excel文件的合并(以新冠疫情数据为例)
Mar 20 Python
Python使用永中文档转换服务
May 06 Python
通过数据库对Django进行删除字段和删除模型的操作
Jul 21 #Python
通过数据库向Django模型添加字段的示例
Jul 21 #Python
Django的数据模型访问多对多键值的方法
Jul 21 #Python
举例讲解Django中数据模型访问外键值的方法
Jul 21 #Python
编写自定义的Django模板加载器的简单示例
Jul 21 #Python
详解Python的Django框架中inclusion_tag的使用
Jul 21 #Python
剖析Django中模版标签的解析与参数传递
Jul 21 #Python
You might like
php图像处理函数大全(推荐收藏)
2013/07/11 PHP
php简单判断文本编码的方法
2015/07/30 PHP
针对thinkPHP5框架存储过程bug重写的存储过程扩展类完整实例
2018/06/16 PHP
解放web程序员的输入验证
2006/10/06 Javascript
Javascript 获取LI里的内容
2008/12/17 Javascript
javascript FormatNumber函数实现方法
2008/12/30 Javascript
jquery.alert 弹出式复选框实现代码
2009/06/15 Javascript
jQuery插件-jRating评分插件源码分析及使用方法
2012/12/28 Javascript
jquery上传插件fineuploader上传文件使用方法(jquery图片上传插件)
2013/12/05 Javascript
对Jquery中的ajax再封装,简化操作示例
2014/02/12 Javascript
网站内容禁止复制和粘贴、另存为的js代码
2014/02/26 Javascript
浅谈JavaScript for循环 闭包
2016/06/22 Javascript
最棒的Angular2表格控件
2016/08/10 Javascript
使用vue实现简单键盘的示例(支持移动端和pc端)
2017/12/25 Javascript
vue项目实现记住密码到cookie功能示例(附源码)
2018/01/31 Javascript
Mac下通过brew安装指定版本的nodejs教程
2018/05/17 NodeJs
看看“疫苗查询”小程序有温度的代码
2018/07/31 Javascript
修改layui的后台模板的左侧导航栏可以伸缩的方法
2019/09/10 Javascript
vue 解决setTimeOut和setInterval函数无效报错的问题
2020/07/30 Javascript
vue将data恢复到初始状态 && 重新渲染组件实例
2020/09/04 Javascript
[04:30]显微镜下的DOTA2第五期——拉比克
2013/09/26 DOTA
Python实现查找系统盘中需要找的字符
2015/07/14 Python
python函数中return后的语句一定不会执行吗?
2017/07/06 Python
Python为何不能用可变对象作为默认参数的值
2019/07/01 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
2019/08/15 Python
Django实现文件上传下载功能
2019/10/06 Python
python getpass模块用法及实例详解
2019/10/07 Python
python 获取域名到期时间的方法步骤
2021/02/10 Python
css3实现冲击波效果的示例代码
2018/01/11 HTML / CSS
澳大利亚婴儿、幼儿和儿童在线设计师商店:Smooch Baby
2019/02/16 全球购物
简历中求职的个人自我评价
2013/12/03 职场文书
生物科学专业个人求职信范文
2013/12/07 职场文书
2014国庆节幼儿园亲子活动方案
2014/09/16 职场文书
公务员个人总结
2015/02/12 职场文书
2019中小学生安全过暑期倡议书
2019/06/24 职场文书
MySQL一劳永逸永久支持输入中文的方法实例
2022/08/05 MySQL