在 Django 中重用 filter() 查询集
Reuse filter() queryset in Django
我想写一个过滤器,到处复用,我该怎么做?
例如:有一个模型 Student
带有标志 field
。我想写一个过滤器来获取非研究生(flag=0
)。但是在很多view和function中我们需要list非研究生,我比较懒,不想在这些view和function中一遍又一遍的写filter,源码很难维护。
我可以在模型 Student 中使用元数据吗?我没有找到任何过滤器相关的元选项。或者我可以写一个函数来过滤模型 Student 吗?在我看来,模型中的函数只适用于一个学生对象而不是列表。
您可以使用自定义管理器来保持内容干燥并增强可读性(明确命名的过滤器总是比拖动复杂的过滤器更好)
class GraduateManager(models.Manager):
def get_queryset(self):
return super(GraduateManager, self).get_queryset().filter(graduated=True)
class UndergraduateManager(models.Manager):
def get_queryset(self):
return super(Undergraduate, self).get_queryset().filter(graduated=False)
class Student(models.Model):
graduated = BooleanField()
graduates = GraduateManager()
undergraduates = UndergraduateManager()
要使用它,您会得到一个可以根据需要操作的普通查询集
Student.graduates.all(), or .filter(), or .count() etc
引用https://docs.djangoproject.com/en/1.8/topics/db/managers/#modifying-initial-manager-querysets
使用自定义 QuerySet 和 QuerySet.as_manager() 是目前最好的解决方案。 Dabapps 的 Jamie Matthews 在他的博客 post Building a higher-level query API: the right way to use Django's ORM.
中详细讨论了可重复使用的过滤器
“Using Django's low-level ORM query methods directly in a view is (usually) an anti-pattern”
— Jamie Matthews
博客 post 是在 Django 获得 .as_manager() method for QuerySet 之前写的。
我现在会使用这样的东西(基于 ):
class StudentQuerySet(models.query.QuerySet):
def graduate(self):
return self.filter(graduated=True)
def undergraduate(self):
return self.filter(graduated=False)
class Student(models.Model):
graduated = BooleanField()
objects = StudentQuerySet.as_manager()
在其他更复杂的情况下,能够在自定义查询集中定义复杂的过滤器很有用,因为过滤器在像这样实现时是可链接的。
如果您希望其他模型中的相关经理可以使用它(即,如果您有另一个模型引用 Student 模型并且正在使用 otherinstance.student_set.all()
),请参阅 Django: Using managers for related object access。简而言之,这样做:
class Student(models.Model):
graduated = BooleanField()
objects = StudentQuerySet.as_manager()
objects.use_for_related_fields = True
我想写一个过滤器,到处复用,我该怎么做?
例如:有一个模型 Student
带有标志 field
。我想写一个过滤器来获取非研究生(flag=0
)。但是在很多view和function中我们需要list非研究生,我比较懒,不想在这些view和function中一遍又一遍的写filter,源码很难维护。
我可以在模型 Student 中使用元数据吗?我没有找到任何过滤器相关的元选项。或者我可以写一个函数来过滤模型 Student 吗?在我看来,模型中的函数只适用于一个学生对象而不是列表。
您可以使用自定义管理器来保持内容干燥并增强可读性(明确命名的过滤器总是比拖动复杂的过滤器更好)
class GraduateManager(models.Manager):
def get_queryset(self):
return super(GraduateManager, self).get_queryset().filter(graduated=True)
class UndergraduateManager(models.Manager):
def get_queryset(self):
return super(Undergraduate, self).get_queryset().filter(graduated=False)
class Student(models.Model):
graduated = BooleanField()
graduates = GraduateManager()
undergraduates = UndergraduateManager()
要使用它,您会得到一个可以根据需要操作的普通查询集
Student.graduates.all(), or .filter(), or .count() etc
引用https://docs.djangoproject.com/en/1.8/topics/db/managers/#modifying-initial-manager-querysets
使用自定义 QuerySet 和 QuerySet.as_manager() 是目前最好的解决方案。 Dabapps 的 Jamie Matthews 在他的博客 post Building a higher-level query API: the right way to use Django's ORM.
中详细讨论了可重复使用的过滤器“Using Django's low-level ORM query methods directly in a view is (usually) an anti-pattern”
— Jamie Matthews
博客 post 是在 Django 获得 .as_manager() method for QuerySet 之前写的。
我现在会使用这样的东西(基于
class StudentQuerySet(models.query.QuerySet):
def graduate(self):
return self.filter(graduated=True)
def undergraduate(self):
return self.filter(graduated=False)
class Student(models.Model):
graduated = BooleanField()
objects = StudentQuerySet.as_manager()
在其他更复杂的情况下,能够在自定义查询集中定义复杂的过滤器很有用,因为过滤器在像这样实现时是可链接的。
如果您希望其他模型中的相关经理可以使用它(即,如果您有另一个模型引用 Student 模型并且正在使用 otherinstance.student_set.all()
),请参阅 Django: Using managers for related object access。简而言之,这样做:
class Student(models.Model):
graduated = BooleanField()
objects = StudentQuerySet.as_manager()
objects.use_for_related_fields = True