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


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

    这些方法的使用:

  • 相关阅读:
    oss blob上传
    app中画一条细线
    antd和原生交互,原生掉前端的方法
    -webkit-touch-callout 图片下载
    ifram嵌入网址 有跨域问题
    ...state
    数组对象的复制
    在vue中使用tinymce组件
    autofs自动挂载服务
    podmen
  • 原文地址:https://www.cnblogs.com/hooo-1102/p/11950729.html
Copyright © 2020-2023  润新知