详解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 ORM框架SQLAlchemy学习笔记之数据添加和事务回滚介绍
Jun 10 Python
python使用wxpython开发简单记事本的方法
May 20 Python
Python中列表和元组的相关语句和方法讲解
Aug 20 Python
Python使用logging结合decorator模式实现优化日志输出的方法
Apr 16 Python
Python实现复杂对象转JSON的方法示例
Jun 22 Python
Python实现的单向循环链表功能示例
Nov 10 Python
对Python中创建进程的两种方式以及进程池详解
Jan 14 Python
Python Matplotlib实现三维数据的散点图绘制
Mar 19 Python
pyqt实现.ui文件批量转换为对应.py文件脚本
Jun 19 Python
jupyter lab文件导出/下载方式
Apr 22 Python
什么是Python包的循环导入
Sep 08 Python
Python基于百度AI实现抓取表情包
Jun 27 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
分页显示Oracle数据库记录的类之一
2006/10/09 PHP
随机头像PHP版
2006/10/09 PHP
php下将XML转换为数组
2010/01/01 PHP
php后台多用户权限组思路与实现程序代码分享
2012/02/13 PHP
Thinkphp中数据按分类嵌套循环实现方法
2014/10/30 PHP
一个简单安全的PHP验证码类 附调用方法
2016/06/24 PHP
JS效率个人经验谈(8-15更新),加入range技巧
2007/01/09 Javascript
JavaScript CSS修改学习第三章 修改样式表
2010/02/19 Javascript
基于jQuery的表格操作插件
2010/04/22 Javascript
js的写法基础分析
2011/01/17 Javascript
Web开发之JavaScript
2012/03/29 Javascript
javascript与cookie 的问题详解
2013/11/11 Javascript
不要使用jQuery触发原生事件的方法
2014/03/03 Javascript
jQuery使用prepend()方法在元素前添加内容用法实例
2015/03/26 Javascript
JavaScript实现页面跳转的方式汇总
2016/05/16 Javascript
javascript如何定义对象数组
2016/06/07 Javascript
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
2017/03/21 jQuery
JavaScript实现弹出广告功能
2017/03/30 Javascript
解决VUEX刷新的时候出现数据消失
2017/07/03 Javascript
删除table表格行的实例讲解
2017/09/21 Javascript
vue cli构建的项目中请求代理与项目打包问题
2018/02/26 Javascript
Nuxt的路由动画效果案例
2020/11/06 Javascript
[01:10:24]DOTA2-DPC中国联赛 正赛 VG vs Aster BO3 第一场 2月28日
2021/03/11 DOTA
数组保存为txt, npy, csv 文件, 数组遍历enumerate的方法
2018/07/09 Python
在numpy矩阵中令小于0的元素改为0的实例
2019/01/26 Python
详解Python:面向对象编程
2019/04/10 Python
python 一个figure上显示多个图像的实例
2019/07/08 Python
pytorch 图像中的数据预处理和批标准化实例
2020/01/15 Python
python加密解密库cryptography使用openSSL生成的密匙加密解密
2020/02/11 Python
django 解决自定义序列化返回处理数据为null的问题
2020/05/20 Python
Python 打印自己设计的字体的实例讲解
2021/01/04 Python
自我鉴定怎么写
2013/12/05 职场文书
一名女生的自荐信
2013/12/08 职场文书
学生未请假就回家检讨书
2014/09/22 职场文书
2016年记者节感言
2015/12/08 职场文书
网络安全倡议书(3篇)
2019/09/18 职场文书