转载自: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保持一致.
现在我们可以进行下面的操作:

Django 自定义模型管理器(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)    # 将类方法包装为属性

这些方法的使用:

Django 自定义模型管理器(Manager)及方法