zoukankan      html  css  js  c++  java
  • 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)    # 将类方法包装为属性

    这些方法的使用:

  • 相关阅读:
    Flutter form 的表单 input
    FloatingActionButton 实现类似 闲鱼 App 底部导航凸起按钮
    Flutter 中的常见的按钮组件 以及自 定义按钮组件
    Drawer 侧边栏、以及侧边栏内 容布局
    AppBar 自定义顶部导航按钮 图标、颜色 以及 TabBar 定义顶部 Tab 切换 通过TabController 定义TabBar
    清空路由 路由替换 返回到根路由
    应对ubuntu linux图形界面卡住的方法
    [转] 一块赚零花钱
    [转]在树莓派上搭建LAMP服务
    ssh保持连接
  • 原文地址:https://www.cnblogs.com/hooo-1102/p/11950729.html
Copyright © 2011-2022 走看看