轉載自: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) # 將類方法包裝為屬性
這些方法的使用: