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 baseManager
class and instantiating your customManager
in your model.There are two reasons you might want to customize a
Manager
: to add extraManager
methods, and/or to modify the initialQuerySet
theManager
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 customManager
methods.)A custom
Manager
method can return anything you want. It doesn’t have to return aQuerySet
.
关于使 models 肥胖(胖模型瘦控制器)还是抽离(业务逻辑应当在Django的什么位置)的讨论不是本文的目的。有兴趣可以参考如下链接
Where to put business logic in Django
Django Best Practices — Refactoring Django Fat Models
个人觉得业务逻辑存放于何处取决于你们团队最初的设计 DDD MVC 等。当然在不同设计模式下也有不同实现方式,有机会我们在共同学习分享!