1. 程式人生 > >Django自定義管理器

Django自定義管理器

在Django中,我們有些時候使用Django自帶的ORM語句無法達到操作資料庫的效果,這時,我們可以自定義一個管理器來進行資料庫的操作。從總體上來說,就是重寫方法和自定義方法

因為不同的操作在不同的類中,如all() 在Manager類,get()在Query類中,所以通過例子說明。

model類:

class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30,null=False)
    sgender = models.BooleanField(default=False)

    def __str__(self):
        return "Student:%s--%s"%(self.sname,self.sgender)

資料庫表資料:


例1:如何通過Student.objects.all() 查詢sgender為True的記錄?

    思路:建立一個類,繼承Manager,然後在這個類中重寫all()方法。在all()方法中新增功能。然後在model類中,定義一個objects屬性,使它成為類物件。(方法有很多,這是其中之一)

程式碼如下:

class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30,null=False)
    sgender = models.BooleanField(default=False)

    objects = getAllTrue()  #建立一個自定義類物件

    def __str__(self):
        return "Student:%s--%s"%(self.sname,self.sgender)
#自定義管理類
class getAllTrue(Manager):  #all()來自於Manager類
    # def all(self):      #重寫方法
    #     return Manager.all(self).filter(sgender = True) #功能操作

    #-----def get_queryset(self): 與all() 方法相同,
    #在原始碼中,all()執行就是呼叫get_queryset()方法。
    def get_queryset(self):
        return Manager.get_queryset(self).filter(sgender=True)
#查詢結果:
Student.objects.all()
#Out[3]: <QuerySet [<Student: Student:zhangsan--True>, <Student: Student:zhaoliu--True>, <Student: Student:qianqi--True>]>

例2:如何使用Student.objects.filter().delete()方法,批量修改sgender=Flase的記錄為True。

    思路:建立一個類,繼承Manager,然後在這個類中重寫filter()方法。在filter()方法中新增功能。然後在model類中,定義一個objects屬性,使它成為類物件。(方法有很多,這是其中之一)

程式碼如下:

class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30,null=False)
    sgender = models.BooleanField(default=False)

    objects = batchDelManager() #建立一個自定義類物件

    def __str__(self):
        return "Student:%s--%s"%(self.sname,self.sgender)

#自定義管理類
class batchDelManager(Manager):
    def filter(self, *args, **kwargs):
        delList = Manager.get_queryset(self)    #獲取所有sgender=False記錄

        #閉包,執行修改操作
        def del1(queset):
            for que in queset:
                que.sgender = True
                que.save()
        import types
        #動態生成方法,使filter().delete()執行del1()方法。
        #types.MethodType在2.x中不能使用,###python2.x使用 new.instancemethod 該方法在python3.x中刪除
        delList.delete = types.MethodType(del1,delList)
        return delList

    def get_queryset(self):
        return Manager.get_queryset(self).filter(sgender=False)

執行程式碼:

Student.objects.filter().delete()

資料庫結果:


例3:Student.objects.create(sname='xiaoming',cls='PythonDjango班',cour=('Python','Django','JS'))不管主外來鍵,直接插入,重寫create方法。

程式碼如下:

from django.db import models
from django.db.models.manager import Manager

#自定義管理類
class CustomManager(Manager):
    #插入班級,以班級作為物件返回
    def getClazz(self,cname):
        try:
            cls = Clazz.objects.get(cname=cname)
        except Clazz.DoesNotExist:
            cls = Clazz.objects.create(cname=cname)
        return cls
    #插入課程,以物件列表返回
    def getcourList(self,course):
        courList = []
        for co in course:
            try:
                cour = Course.objects.get(course_name=co)
            except Course.DoesNotExist:
                cour = Course.objects.create(course_name=co)
            courList.append(cour)
        return courList

    def create(self, **kwargs):
        cname = kwargs['cls']
        clazz = self.getClazz(cname)

        kwargs['cls'] = clazz   #班級

        course = kwargs.pop('cour') #丟擲課程給course

        stu = Manager.create(self,**kwargs)     #儲存學生

        courseList = self.getcourList(course)

        stu.cour.add(*courseList)   #新增學生與課程的連線


# Create your models here.
class Clazz(models.Model):
    cno = models.AutoField(primary_key=True)
    cname = models.CharField(max_length=30)

    def __str__(self):
        return 'Clazz:%s'%self.cname

class Course(models.Model):
    course_no = models.AutoField(primary_key=True)
    course_name = models.CharField(max_length=30)

    def __str__(self):
        return 'Course:%s'%self.course_name

class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30)
    cls = models.ForeignKey(Clazz,on_delete=models.CASCADE)
    cour = models.ManyToManyField(Course)

    objects = CustomManager()

    def __str__(self):
        return 'Student:%s'%self.sname