详解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 相关文章推荐
python实现自动更换ip的方法
May 05 Python
详解supervisor使用教程
Nov 21 Python
windows环境下tensorflow安装过程详解
Mar 30 Python
Python寻找两个有序数组的中位数实例详解
Dec 05 Python
详解利用Python scipy.signal.filtfilt() 实现信号滤波
Jun 05 Python
利用Python实现Shp格式向GeoJSON的转换方法
Jul 09 Python
Python之虚拟环境virtualenv,pipreqs生成项目依赖第三方包的方法
Jul 23 Python
利用python实现周期财务统计可视化
Aug 25 Python
python创建n行m列数组示例
Dec 02 Python
Python语言异常处理测试过程解析
Jan 08 Python
Python 实现打印单词的菱形字符图案
Apr 12 Python
尝试使用Python爬取城市租房信息
Apr 12 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实现的遍历文件夹下所有文件,编辑删除
2010/01/05 PHP
又拍云异步上传实例教程详解
2016/04/19 PHP
IE6中使用position导致页面变形的解决方案(js代码)
2011/01/09 Javascript
iframe里面的元素触发父窗口元素事件的jquery代码
2014/10/19 Javascript
JavaScript Math.floor方法(对数值向下取整)
2015/01/09 Javascript
javascript常用功能汇总
2015/07/05 Javascript
javascript添加前置0(补零)的几种方法
2017/01/05 Javascript
servlet+jquery实现文件上传进度条示例代码
2017/01/25 Javascript
基于Angular.js实现的触摸滑动动画实例代码
2017/02/19 Javascript
利用jQuery实现一个简单的表格上下翻页效果
2017/03/14 Javascript
layui文件上传实现代码
2017/05/20 Javascript
three.js中文文档学习之通过模块导入
2017/11/20 Javascript
jQuery实现带右侧索引功能的通讯录示例【附源码下载】
2018/04/17 jQuery
vue源码学习之Object.defineProperty 对数组监听
2018/05/30 Javascript
详解小程序不同页面之间通讯的解决方案
2018/11/23 Javascript
JS获取一个字符串中指定字符串第n次出现的位置
2021/02/10 Javascript
python选择排序算法的实现代码
2013/11/21 Python
python数据结构之二叉树的建立实例
2014/04/29 Python
Python使用scrapy采集数据时为每个请求随机分配user-agent的方法
2015/04/08 Python
python执行get提交的方法
2015/04/29 Python
Python对字符串实现去重操作的方法示例
2017/08/11 Python
python实现两张图片的像素融合
2019/02/23 Python
python中bs4.BeautifulSoup的基本用法
2019/07/27 Python
python操作openpyxl导出Excel 设置单元格格式及合并处理代码实例
2019/08/27 Python
wxPython实现分隔窗口
2019/11/19 Python
Python 剪绳子的多种思路实现(动态规划和贪心)
2020/02/24 Python
基于python实现把json数据转换成Excel表格
2020/05/07 Python
简单了解如何封装自己的Python包
2020/07/08 Python
浅析python函数式编程
2020/09/26 Python
html5 移动端视频video的android兼容(去除播放控件、全屏)
2020/03/26 HTML / CSS
安纳塔拉酒店度假村及水疗官方网站:Anantara Hotel
2016/08/25 全球购物
关于爱情的广播稿
2014/01/16 职场文书
创业女性典型材料
2014/05/02 职场文书
销售员试用期自我评价
2014/09/15 职场文书
python代码实现备忘录案例讲解
2021/07/26 Python
彻底卸载VMware虚拟机的超详细步骤记录
2022/07/15 Servers