Django中自定义模型管理器(Manager)及方法
作者:迎风而来 发布时间:2022-12-01 17:53:05
1.自定义管理器(Manager)
在语句Book.objects.all()中, objects 是一个特殊的属性,通过它来查询数据库,它就是模型的一个Manager.
每个Django模型至少有一个manager,你可以创建自定义manager以定制数据库的访问.
这里有两个方法创建自定义manager:添加额外的manager;修改manager返回的初始Queryset.
添加额外的manager
增加额外的manager是为模块添加 表级功能 的首选办法.(至于 行级功能 ,也就是只作用于模型实例对象的函数,则通过自定义模型方法实现).
例如,为Book模型添加一个 title_count() 的manger方法,它接收一个 keyword ,并返回标题中包含 keyword 的书的数量.
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保持一致.
现在我们可以进行下面的操作:
>>> Books.objects.title_count('django') #这是我们自定义的manager中的查询方法
>>> Books.objects.filter(title__icontains='django').count() # 默认的查询方法依然可用
这样我们可以将经常使用的查询进行封装,就不必重复写代码了.
修改初始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() 了,你可能接受到一个无用的返回对像,你必须避免这种情况.
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) # 将类方法包装为属性
这些方法的使用:
>>> p = Person.objects.get(first_name='Barack', last_name='Obama')
>>> p.birth_date
datetime.date(1961, 8, 4)
>>> p.baby_boomer_status()
'Baby boomer'
>>> p.full_name # 注意这不是一个方法 -- 它被视为一个属性
'Barack Obama'3.重写预定义的模型方法
还有一组模型方法了封装了一些你可能想要自定义的数据库行为.特别是你可能想要修改 save() 和 delete() 的工作方式.你可以自由的重写这些方法(以及其他的模型方法)来改变行为.重写内置方法的经典用例就是你想要在保存一个对象是做些其他的什么.例如:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
do_something()
super(Blog, self).save(*args, **kwargs) #Call the "real" save() method.
do_something_else()
你也可以阻止保存行为:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
if self.name == 'Yoko Ono's Blog':
return # Yoko shall never have her own blog!
else:
super(Blog, self).save(*args, **kwargs) #Call the "real" save() method
记住,继承超类的方法非常重要,即 super(Blog, self).save(*args, **kwargs)
,它确保该对象仍被保存到数据库中.如果你忘记调用超类方法,那么默认的行为将不会发生,也不会发生数据库操作.
同样重要的是,您要传递可以传递给模型方法的参数——这就是 *args, **kwargs 所做的事情。Django将不时扩展内置模型方法的功能,并添加新的参数。如果您在方法定义中使用了 *args, **kwargs ,您将保证您的代码在添加时将自动支持这些参数。
Model.clean()
应用这个方法来提供自定义的模型验证,以及修改模型的属性.例如,你可以使用它来给一个字段自动提供值,或者用于多个字段需要一起验证的情形:
import detetime
from django.core.exceptions import ValidationError
from django.db import models
class Article(models.Model):
...
def clean(self):
# Don't allow draft entries to have a pub_date
if self.status == 'draft' and self.pub_date is not done:
raise ValidationEroor('Draft entries may not have a publication date')
#Set the pub_date for published items if it hasn't been set already
if self.status == 'published' and self.pub_date is None:
self.pub_date = datetime.date.today()
注意,调用模型的 save() 方法时,不会自动调用 clean() 方法,需要views手动调用.
上面的示例中, clean() 引发的ValidationError异常通过一个字符串实例化,所以它将被保存在一个特殊的错误字典中,键为 NON_FIELD_ERRORS .这个键用于整个模型出现的错误而不是一个特定字段穿线的错误:
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
try:
article.full_clean()
except ValidationError as e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]
若要引发一个特定字段的异常,可以使用一个字典实例化 ValidationError ,其中字典的键为字段名.我们可以更新前面的例子,只引发 pub_date 字段上的异常:
class Article(models.Model):
...
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError({'pub_date': 'Draft entries may not have a publication date.'})
...
总结
以上所述是小编给大家介绍的Django中自定义模型管理器(Manager)及方法,网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://www.cnblogs.com/sui776265233/p/11571418.html


猜你喜欢
- argparse是python标准库里面用来处理命令行参数的库命令行参数分为位置参数和选项参数:位置参数就是程序根据该参数出现的位置来确定的
- 项目地址:https://github.com/chen0495/pythonCrawlerForJSU环境python 3.5即以上req
- 在批评Python的讨论中,常常说起Python多线程是多么的难用。还有人对 global interpreter lock(也被亲切的称为
- 本次,我们来看看索引、提交频率对InnoDB表写入速度的影响,了解有哪些需要注意的。先直接说几个结论吧:1、关于索引对写入速度的影响:a、如
- 脚手架vue-cli 搭建的项目,build后放于服务器上,发现其他资源全部变成静态加载成功,但路由视图为空,最初以为是webpack打包的
- 源代码:# dict1 是 字典 , 用来对应相应元素的下标,我们将文件转成列表,对应的也就是文件的下标,通过下标来找文件元素dict1 =
- 我们已对 Django1.6 app完成了数据库从mysql到PostgreSQL的迁移,如果你的环境很干净,这个过程就会很简单,只要允许s
- 在日常的网页源码中,我们基于元素的id去定位是最万无一失的,id在单个页面中是不会重复的。但是实际工作中,很多前端开发人员并未给每个元素都编
- 1.图片分类网络这是一个二分类网络,可以是alxnet ,vgg,resnet任何一个,负责对图片进行二分类,区分图片是真实图片还是生成的图
- 一、StreamVR问题:1.运行项目时不显示手柄控制器:出现这种情况一般会在头显中提示不能加载按键配置文件,出现这种提示时请直接打开ste
- 前言因为一些懂得都懂的原因,我的父母对于我电脑上的文件内容特别感兴趣。为了防止信息泄露,我连夜用Python做了一个文件加密器,防止我的重要
- 在Vue项目中编写代码的时候经常会碰到这种烦人的无故报错,其实这是ESLint代码,如图下:解决办法:File>Settings>
- 本文实例讲述了Python爬虫实现网页信息抓取功能。分享给大家供大家参考,具体如下:首先实现关于网页解析、读取等操作我们要用到以下几个模块i
- tempfile.TemporaryFile如何你的应用程序需要一个临时文件来存储数据,但不需要同其他程序共享,那么用TemporaryFi
- 一、在webpack-dev-conf.js文件中:1、在const portfinder = require(‘portfinder
- 首先你要确定错误的原因: 让IE显示详细的出错信息: 菜单--工具--Internet选项--高级--显示友好的HTTP错误信息,去掉这个选
- 1. 系统盘清理说明win7 80G的系统盘,随着使用时间的增加,空间越来越小,只剩不到2G,随计划清理系统盘数据1. maven 下载的j
- 前言日常开发使用到的命令行工具大都支持如下特性:文档自动生成(如 -h --help)多级子命令(如 docker exec -it)支持参
- java连接数据库增、删、改、查工具类数据库操作工具类,因为各厂家数据库的分页条件不同,目前支持Mysql、Oracle、Postgresq
- 1. 引言本文为介绍流行的数独游戏的系列文章中的第一篇。更具体地说,我们如何构建一个脚本来解决数独难题,本文的重点在于介绍用于构建数独求解器