Django模型继承与自定义Manager重写filter方法详解
本文介绍如何在Django中通过定义抽象基类实现模型字段复用,并深入解析如何重写Manager类的filter方法以自动过滤is_active字段。通过继承BaseManager并重写核心查询逻辑,开发者可统一数据访问层行为,减少冗余代码,提升代码的Pythonic程度与维护效率。
Django模型继承与自定义Manager基础
Django自定义管理器与模型继承机制
在开发过程中,许多数据库模型需要包含通用的字段,例如用于标识状态或记录时间的字段。为了复用这些公共字段,可以创建一个基础的模型类作为基类。
模型类的继承结构
利用面向对象编程(OOP)的特性,我们可以构建一个基类模型。后续创建的所有具体模型均可继承该类,从而避免在每个模型中重复定义相同的字段,简化代码结构。
抽象基类BaseModel实现
class BaseModel(models.Model):
is_active = models.BooleanField(default=True)
create_time = models.DateTimeField()
class Meta:
'''
指定这个类是一个抽象模型类, 这个模型就不会被生成表
'''
abstract = True
class ChildModel(BaseModel):
name = models.CharField(max_length=10)
age = models.PositiveIntegerField()
class Meta:
'''
meta属性可以重写, 不重写的话也会继承基类meta
'''
verbose_name = '子模型'
重写Django模型的objects管理器
在使用model.objects.filter()进行查询时,通常希望自动过滤掉is_active为False的记录。如果每次查询都手动添加filter(is_active=True),会导致代码冗余。通过重写filter方法,可以实现自动过滤。以下结合Django源码进行分析。
自定义Manager重写filter逻辑
# 这里源码我就不拉出来了, 我们可以看到django是set了个objects属性, 这个属性对应是一个类的实例对象
class Manager(BaseManager.from_queryset(QuerySet)):
'''
objects 是这个类的实例对象, 这个类我们可以看到他其实继承了 QuerySet类里的方法,
所以我们可以直接重写个这个类方法,并重写filter方法
'''
def filter(self, *args, **kwargs):
"""
我们可以看到 QuerySet里的filter方法和exclude方法都是调用了这个方法, 这个方法的内部实现可
以自己看一看,就是用的kwargs里的参数
"""
return self._filter_or_exclude(False, *args, **kwargs)
class MyManager(models.Manager):
def filter(self, *args, **kwargs):
'''
源代码的filter函数是有返回值的,所以我们将super出来的结果返回出去,我们只需要在kwargs中增加个参数就行
'''
if not kwargs.get('is_active', True): # 如果需要查看所有数据,
kwargs['is_active'] = False
return super(AddressManager, self).filter(*args, **kwargs)
# 最后我们在我们的ChildModel下将objects对象赋值为MyManager的实例对象就可以使用了
# 我们可以将这个objects写在基类里面,这样所有的model就可以都会有这个方法,具体怎么使用视情况而定
class ChildModel(models.Model):
objects = MyManager()
模型类支持多继承,若有特殊需求可进一步查阅文档或搜索相关案例。此处主要引入面向对象的概念,展示如何通过继承框架现有类并重写方法,使代码更加符合Pythonic风格。
Django Model字段属性与选项详解
补充知识:Django Model字段属性与选项配置
常见字段类型包括:
autoField:自动增长的IntegerField,通常不显式指定。若不指定,Django会自动添加一个主键字段。
CharField(max_length=字符长度):用于存储字符串,默认表单控件为TextInput。
TextField:用于存储大文本,通常当内容超过4000字符时使用,默认表单控件为Textarea。
IntegerField:用于存储整数。
DecimalField(max_digits=None, decimal_places=None):使用Python的Decimal实例表示十进制浮点数。
参数说明:DecimalField.max_digits表示总位数,DecimalField.decimal_places表示小数点后的位数。
FloatField:使用Python的float实例表示浮点数。
BooleanField:存储True/False值,默认表单控件为CheckboxInput。
NullBooleanField:支持Null、True、False三种值。
DateField([auto_now=False, auto_now_add=False]):使用Python的datetime.date实例表示日期。
参数说明:DateField.auto_now在每次保存对象时自动设置为当前时间,用于记录“最后一次修改”的时间戳,默认为False。
DateField.auto_now_add
在对象首次创建时自动设置为当前时间,用于记录创建时间戳。
该设置始终使用当前日期,默认为False。
说明:该字段默认对应的表单控件是TextInput。在管理员站点中,会添加一个由JavaScript编写的日历控件和一个“Today”快捷按钮,并包含额外的invalid_date错误消息键。注意:auto_now_add、auto_now和default这些设置是互斥的,任何组合使用都可能导致错误结果。
TimeField:使用Python的datetime.time实例表示时间,参数与DateField相同。
DateTimeField:使用Python的datetime实例表示日期和时间,参数与DateField相同。
FileField:用于存储上传的文件。
ImageField:继承自FileField,并对上传对象进行校验,确保其为有效的图像文件。
字段选项配置
概述:通过字段选项可以对字段进行约束,在字段对象中通过关键字参数指定。
null:若为True,Django将空值以NULL存储在数据库中,默认值为False。
blank:若为True,则该字段允许为空,默认值为False。
注意:null是数据库层面的概念,而blank是表单验证层面的概念。
db_column:指定数据库中的字段名称,若未指定,则使用Python属性的名称。
db_index:若值为True,则在此字段上创建数据库索引。
default:指定字段的默认值。
primary_key:若为True,则该字段成为模型的主键字段。
unique:若为True,则该字段在表中必须具有唯一值。
注意:在生成迁移文件后,如果修改的参数不影响表结构(如default、blank),则无需重新生成迁移文件。
模型关系类型与访问方式
关系类型定义
分类说明:
ForeignKey:一对多关系,字段定义在“多”的一端。
ManyToManyField:多对多关系,字段定义在两端。
OneToOneField:一对一关系,字段定义在任意一端。
(1)用一访问多:格式为对象.模型类小写_set。
示例:grade.students_set。
(2)用一访问一:格式为对象.模型类小写。
示例:grade.studnets。
(3)访问外键ID:格式为对象.属性_id。
例子:btitle = models.CharField(max_length=20,db_column=‘title',unique=‘true')。
以上关于重写Django model下objects模型管理器的内容即为分享的全部,希望能提供参考,欢迎支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













