转载自: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) # 将类方法包装为属性
这些方法的使用: