Django 自定义模型管理器(Manager)及方法
转载自:https://www.cnblogs.com/sui776265233/p/11571418.html
1.自定义管理器(Manager)
在语句Book.objects.all()中,objects
是一个特殊的属性,通过它来查询数据库,它就是模型的一个Manager.
每个Django模型至少有一个manager,你可以创建自定义manager以定制数据库的访问.
这里有两个方法创建自定义manager:添加额外的manager;修改manager返回的初始Queryset.
添加额外的manager
增加额外的manager是为模块添加表级功能的首选办法.(至于行级功能,也就是只作用于模型实例对象的函数,则通过自定义模型方法实现).
例如,为Book模型添加一个title_count()
的manger方法,它接收一个keyword
,并返回标题中包含keyword
的书的数量.
models.py
from django.db import models # 自定义模型管理器类
class BookManager(models.Manager):
#自定义模型管理器中的方法
def title_count(self, keyword):
return self.filter(title_icountains=keyword).count() class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
...
objects = BookManager() def __str__(self):
return self.title
1.我们创建一个BookManager类,继承自django.db.models.Manager
.它只有一个方法title_count()
,来进行统计.注意,这个方法使用了self.filter()
,这个self指manager本身.
2.将BookManager()赋值给模型的objects属性.它将取代模型的默认manager(objects).把它命名为objects是为了与默认的manager保持一致.
现在我们可以进行下面的操作:
这样我们可以将经常使用的查询进行封装,就不必重复写代码了.
修改初始Manager Queryset
manager的基础Queryset返回系统中的所有对象.例如,Book.objects.all()
返回book数据库中的所有书籍.你而已通过覆盖Manager.get_queryset()
方法来重写manager的基础Queryset.get_queryset()
应该按照你的需求返回一个Queryset.
例如,下面的模型有两个manger--一个返回所有对象,另一个仅返回作者是Roald Dahl的书
from django.db import models #首先,定义一个Manager的子类
class DahlBookManager(models.Manager):
def get_queryset(self):
return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl') # 然后,将它显式地插入到Book模型中
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
...
objects = models.Manager() # 默认Manager
dahl_objects = DahlBookManager() # 自定义的特殊Manager
在这个示例模型中,Book.objects.all()
将返回数据库中的所有书籍,而Book.dahl_objects.all()
只返回作者是Roald Dahl的书籍.注意我们明确的将objects
设置为默认Manger的一个实例,因为如果我们不这样做,那么dahl_objects将成为唯一一个可用的manager.
由于get_queryset()
返回一个Queryset对象,所以你可以使用filter()
,exclude()
和其他所有的Queryset方法.
如果你使用自定义的Manager对象,请注意,Django遇到的第一个Manager(以它在模型中被定义的位置为准)会有一个特殊状态。 Django将会把第一个Manager 定义为默认Manager ,Django的许多部分(但是不包括admin应用)将会明确地为模型使用这个manager。 结论是,你应该小心地选择你的默认manager。因为覆盖get_queryset()
了,你可能接受到一个无用的返回对像,你必须避免这种情况.
举个栗子:
models.py:
class StudentsManager(models.Manager):
def get_queryset(self):
return super(StudentsManager,self).get_queryset().filter(isDelete=False)
#在自定义管理器中定义一个方法创建对象
def createStudents(self,name, age, gender, contend, grade, isD = False):
stu = self.model()
#print(type(stu))
stu.sname = name
stu.sage = age
stu.sgender = gender
stu.scontend = contend
stu.sgrade = grade
return stu
class Students(models.Model):
#xx.objects.all()里的objects是一个Manager()对象
#如果有了新的Manager()对象,原来的objects就不能用了,除非新的Manager()对象命名也是objects
stuObj = models.Manager() #stuObj就相当于原来的objects
stuObj2 = StudentsManager() #stuObj2相当于有一个过滤条件(isDelete=False)的objects
sname = models.CharField(max_length=20)
sgender = models.BooleanField(default=True)
sage = models.IntegerField(db_column='age')
scontend = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
sgrade = models.ForeignKey("Grades")
def __str__(self):
return self.sname
# lastTime = models.DateTimeField(auto_now=True)
# createTime = models.DateTimeField(auto_now_add=True)
class Meta:
#改变数据库库名
db_table = "students"
#排序
ordering = ['id'] #在模型类中定义一个类方法创建对象 cls相当于Students类
@classmethod
def createStudents(cls, name, age, gender, contend, grade, isD = False):
stu =cls(sname = name, sage = age,sgender = gender,scontend = contend, sgrade = grade, isDelete = isD)
return stu
views.py:
def students(request):
studentsList = Students.stuObj.all()
return render(request, 'myApp/students.html',{'students':studentsList}) def stupage(request,page):
page = int(page)
studentsList = Students.stuObj2.all()[(page-1)*5:page*5]
return render(request, 'myApp/students.html',{'students':studentsList}) #通过类方法创建对象
def addstudent(request):
grade = Grades.objects.get(pk=1)
stu = Students.createStudents("刘德华",34,True,"我叫刘德华",grade)
stu.save()
return HttpResponse('ok') #通过自定义管理器里的方法创建对象
def addstudent2(request):
grade = Grades.objects.get(pk=1)
stu = Students.stuObj2.createStudents("张学友",43,True,"我叫张学友",grade)
stu.save()
return HttpResponse('ok2')
2.自定义模型方法
为了给你的对像添加一个行级功能,那就定义一个自定义方法.鉴于manager经常被用来用一些整表操作(table-wide).模型方法应该只对特殊模型实例起作用.
from django.db import models class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField() def baby_boomer_status(self):
# Returns the person's baby_boomer status
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return 'Pre-boomer'
elif self.birth_date < datetime.date(1965, 1, 1):
return 'Baby boomer'
else:
return 'Post-boomer' def _get_full_name(self):
# Return the person's full name
return f'{self.first_name} {self.last_name}'
full_name = property(_get_full_name) # 将类方法包装为属性
这些方法的使用:
Django 自定义模型管理器(Manager)及方法的更多相关文章
- Django中自定义模型管理器(Manager)及方法
1.自定义管理器(Manager) 在语句Book.objects.all()中,objects是一个特殊的属性,通过它来查询数据库,它就是模型的一个Manager.每个Django模型至少有一个ma ...
- Django 自定义模型管理器类2个应用场景
class BookManager(models.Manager): # 改变查询集的结果集 def all(self): books = super().all() # QuerySet books ...
- Django之模型管理器filter处理问题
今天上班第一天,恭祝所有朋友新年快乐!! 最近在github上发现一个还不错的基于Django的开源博客项目,不过也许是版本原因,其中代码存在着些许问题,今天主要记录下其中的模型处理方法的部分. 这段 ...
- 查询集 QuerySet和管理器Manager
查询集 QuerySet 查询集,也称查询结果集.QuerySet,表示从数据库中获取的对象集合. 当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表): all():返回所有数据. ...
- Django ORM 查询管理器
Django ORM 查询管理器 ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言 ...
- (转)Java 的swing.GroupLayout布局管理器的使用方法和实例
摘自http://www.cnblogs.com/lionden/archive/2012/12/11/grouplayout.html (转)Java 的swing.GroupLayout布局管理器 ...
- win2008以上的系统,在vmware esxi5.5里怎么使用自定义规范管理器?sysprep
经过测试,原来08以上的系统自带了sysprep.exe,所以vcenter对08以上的系统直接使用自定义规范管理器即可,跟linux一样了.注意不要跟03一样写入了sn即可. vCenter可使用s ...
- Django 源码小剖: Django ORM 查询管理器
ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换.从 ...
- 自定义缓存管理器 或者 Spring -- cache
Spring Cache 缓存是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存. 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 c ...
随机推荐
- PAT 2019-3 7-2 Anniversary
Description: Zhejiang University is about to celebrate her 122th anniversary in 2019. To prepare for ...
- 【excel】 超链接相关
如何导出超链接: 用visual basic处理 在excel中:Alt+F11 --> F7 --> 粘贴下面代码 -->F5(运行), 则会在原列接右侧出现超链 Sub Ext ...
- 利用select单线程点对点聊天
select的优点与使用方法 select用单线程的方法遍历所有待读写的I/O接口, 当有接口可用时就会返回. select可设置电脑阻塞或非阻塞. 特别注意: 每次select前都要重新初始化集合和 ...
- LeetCode6 dp
120. Triangle 我的解法用了一个二维数组,这样比较浪费空间.O(n*n) 但是标准答案自底向上,一是不需要进行特别判断,二是可以覆盖数组,则只需要O(n)的空间大小. class Solu ...
- C++异常处理的深入理解
1,问题: 1,如果在 main 函数中抛出异常会发生什么? 1,不处理,则崩溃: 2,如果异常不处理,最后会传到哪里? 3,下面的代码输出什么? 4,异常的最终处理编程实验: #include &l ...
- 使用腾讯地图请求来源未被授权, 此次请求来源域名/ip:servicewechat.com
原文:微信小程序使用腾讯地图请求来源未被授权, 此次请求来源域名:servicewechat.com 版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明 ...
- maxim - Android UI压力测试
项目介绍 项目地址:https://github.com/zhangzhao4444/Maxim 与monkey对比优势: 快 稳:只进行有意义的操作,防误点状态栏,不会乱断网.卸载应用 支持脱机运行 ...
- C# .NET 和.NET Framework区别
一,C#简介 1>C#是一种面向对象的.运行于.NET Framework之上的高级程序设计语言. 2>C# 是一种简洁.类型安全的面向对象的语言,开发人员可以使用它来构建在 .NET F ...
- MongoDB--副本集基本信息
副本集的概念 副本集是一组服务器,其中有一个是主服务器(primary),用于处理客户端请求:还有多个备份服务器(secondary),用于保存主服务器的数据副本.如果主服务器崩溃了,备份服务器会自动 ...
- 力扣—climbing stairs(爬楼梯) python实现
题目描述: 中文: 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 英文: You are cl ...