我想编写一次过滤器并在任何地方重复使用,我该怎么办?
例如:有一个标有Student
的模型field
。我想写一个过滤器来获得非研究生(flag=0
)。但是在许多视图和函数中,我们需要列出非研究生,我很懒,不想在这些视图和函数中反复编写过滤器,因为这会使维护源代码变得困难。
我可以在模特学生中使用meta吗?我没有找到任何与过滤器相关的元选项。或者我可以编写一个函数来过滤模型学生吗?在我看来,模型中的函数只能在一个Student对象而不是list中工作。
答案 0 :(得分:3)
您可以使用自定义管理器来保持DRY并提高可读性(明确命名的过滤器总是比拖动复杂的过滤器更好)
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
答案 1 :(得分:2)
现在使用自定义QuerySet和QuerySet.as_manager()是最佳解决方案。 Dabapps的Jamie Matthews在他的博文Building a higher-level query API: the right way to use Django's ORM中详细讨论了可重复使用的过滤器。
“直接在视图中使用Django的低级ORM查询方法(通常)是一种反模式”
- 杰米马修斯
博客文章是在Django为QuerySet获取.as_manager() method之前编写的。
我现在使用这样的东西(基于currently accepted answer):
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()
在其他更复杂的情况下,能够在自定义查询集中定义复杂过滤器非常有用,因为过滤器在实现时可以链接。
如果您希望其他模型中的相关管理员可以使用此功能(例如,如果您有其他模型引用学生模型并使用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