Django Manager Queryset

Django Manager Queryset

1.ORM objects

我们使用 Django ORM进行数据库操作时,默认使用的Manager 对象是objects,每个Django模型默认拥有一个。

类似如下情况:

from django.db import models


class Student(models.Model):
    name=models.CharField(max_length=128)
    ...
    objects=models.Manger()
    def get_student_by_name(self, name):
        return self.objects.get(name=name)

2.自定义Manager

class StudentManager(models.Manager):
    def  get_student_by_name(self, name):
        return self.filter(name=name)
    def get_student_by_id(self, id):
        return self.filter(id=id)

class Student(models.Model):
    ...
    modify = StudentManager()

ORM语句

models.Student.modify.get_student_by_name(name)

当我们只使用自定义Manager对象查询时,各个自定义方法是不能够链接的

例如下面语法是错误的(此处的语句没有意义,仅用来说明问题)

models.Student.modify.get_student_by_name(name=name).get_student_by_id(id=id)

3.自定义queryset


class StudentManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filetr(...)
    
    def  get_student_by_name(self, name):
        return self.filter(name=name)
    
    def get_student_by_id(self, id):
        return self.filter(id=id)

class Student(models.Model):
    ...
    modify = StudentManager()

此时,我们使用如下语句查询会得到我们想要的QuerySet对象

models.student.modify.all()

对于三多提出的不能链接的问题此处就可以使用如下实例解决:

class StudentQuerySet(models.QuerySet):
	def get_queryset(self):
        super().get_queryset().filetr(...)
        
	def  get_student_by_name(self, name):
        return self.filter(name=name)
    
    def get_student_by_id(self, id):
        return self.filter(id=id)

    
class StudentManager(models.Manager):
    def get_queryset(self):
        return StudentQuerySet.get_queryset()
    
    def  get_student_by_name(self, name):
        return self.filter(name=name)
    
    def get_student_by_id(self, id):
        return self.filter(id=id)

class Student(models.Model):
    ...
    modify = StudentManager()

此时,如下语句是没有问题的:

models.Student.modify.get_student_by_name(name=name).get_student_by_id(id=id)

此时,我们会发现QuerySet 和Manager 有重复代码。

使用as_manager解决

如下,我们不直接实例化StudentManager类

class Student(models.Model):
    ...
    modify = StudentQuerySet.as_manager()

4.总结

Django 官网指出,

You can use a custom Manager in a particular model by extending the base Manager class and instantiating your custom Manager in your model.

There are two reasons you might want to customize a Manager: to add extra Manager methods, and/or to modify the initial QuerySet the Manager returns.

Adding extra Manager methods is the preferred way to add “table-level” functionality to your models. (For “row-level” functionality – i.e., functions that act on a single instance of a model object – use Model methods, not custom Manager methods.)

A custom Manager method can return anything you want. It doesn’t have to return a QuerySet.

关于使 models 肥胖(胖模型瘦控制器)还是抽离(业务逻辑应当在Django的什么位置)的讨论不是本文的目的。有情趣可以参考如下链接

Where to put business logic in Django

Django Best Practices — Refactoring Django Fat Models

个人觉得业务逻辑存放于何处取决于你们团队最初的设计 DDD MVC 等。当然在不同设计模式下也有不同实现方式,有机会我们在共同学习分享!

原文地址:https://www.cnblogs.com/9527mwz/p/13588723.html