在我写代码时建立的很多数据库需要一些共同的字段,比如is_active, create_time这些字段,所以可以建立一个基类model
我们可以充分利用oop特性,建立一个基类model,以后所有的model都继承这个类, 就不用在每个类都额外添加字段
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 = '子模型'
当我们使用model.objects.filter()时,经常会过滤掉is_active=False
的,但是这样我们每个 filter(is_active=True)
都需要这样写,那我们能不能重写掉这个filter方法, 让他每次可以自己过滤掉,这里我们可以看一下django的源码
# 这里源码我就不拉出来了, 我们可以看到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()
最后最后,我也是一个小菜鸟,只是在不断的学习中发现一些非常实用的小技巧和方法我就会想记录下来,有时想写一个文章但是隔了很久之后才想起来,所以有地方可能会有遗漏,对一些地方也有些理解的不是很到位,写的文章可能会有些小错误,可以告诉我,我们可以及时交流