重寫django的model下的objects模型管理器
阿新 • • 發佈:2018-11-11
django自定義管理器和model的繼承
在我寫程式碼時建立的很多資料庫需要一些共同的欄位,比如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 = '子模型'
重寫Django的model.objects
當我們使用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()
模型類也是可以多繼承的,如果有特殊的用法可以具體百度或Google一下, 這裡只是個簡單的引入面向物件的概念,我們很多地方可以用繼承框架已有的類並重寫類中的方法,是我們的程式碼更加pythonic
最後最後,我也是一個小菜鳥,只是在不斷的學習中發現一些非常實用的小技巧和方法我就會想記錄下來,有時想寫一個文章但是隔了很久之後才想起來,所以有地方可能會有遺漏,對一些地方也有些理解的不是很到位,寫的文章可能會有些小錯誤,可以告訴我,我們可以及時交流