很难看到自定义Django模型管理器的效用



我没有任何关于这个问题的代码,所以这将更多地是关于客户经理的实用性,而不是实现问题。

我已经阅读了文档、许多博客文章,并尝试自己实现一些,但在Django自定义模型管理器中找不到实用工具。我知道它们可以帮助分割代码,也可以帮助DRY原则,但我很难理解如何做到这一点。所以这个问题可以分解为几个子点

  • 这对DRY原理有何帮助
  • 这对代码分割有什么帮助
  • 管理者可以做viewsmodel方法不能做的事情

您可以在管理器中封装过滤、注释、子查询等。例如:

class ActiveManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
active=True
)

然后将其应用于具有active字段的模块:

class MyActiveModel(models.Model):
active= models.BooleanField(default=False)
objects = ActiveManager()

现在,如果我们使用MyActiveModel.objects.all(),它将只检索具有active = True的记录。因此,我们不需要在所有视图中应用这种过滤,我们可以像在任何模型中一样使用objects,它将透明地过滤对象。

如果要对查询集进行扩展,还经常使用Manager

例如,我们可以定义一个AuthorQuerySet,它提供了一个额外的方法.of_user(…),例如,在给定用户是作者或用户是超级用户的情况下保留记录,使用检索所有记录

class AuthorQuerySet(models.QuerySet):
def from_user(self, user):
if user.is_superuser:
return self
else:
return self.filter(author=user)

然后与允许进行这种过滤的管理器合作:

from django.conf import settings
class Post(models.Model):
author= models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
objects = AuthorQuerySet.as_manager()

然后我们可以检索用户可以看到的对象:

Post.objects.filter_user(myuser)

或者在一系列过滤器中这样做:

Post.objects.filter(title__istartswith='The').filter_user(myuser)

因此,它主要处理封装逻辑,这样过滤、注释等只定义一次,然后以透明的方式在视图中使用。换句话说,视图不需要担心只检索活动对象,管理器会处理好这一点。

这对代码分割有什么帮助?

模型专注于在数据库中存储记录并显示数据。通常情况下,它应该而不是来决定您在什么情况下看到什么记录。视图用于此。但是,如果逻辑是相同的,那么在视图中写这篇文章就没有意义了,因为在这种情况下,(几乎)总是应该发生的过滤、注释等被复制到大量视图中,这会使代码容易出错。通过在管理器中实现这一点,我们在模型和视图之间有了一层,可以始终以相同的方式过滤、注释等数据。

视图或模型方法不能做的管理者能做什么?

每个视图可以重复一次相同的筛选代码,但这使得以后在流程中很难更改该逻辑,因为之后应该查看访问这些模型的视图,并对所有视图进行更改。这会使人们很容易忽视一些东西,从而导致不一致的状态。

还可以在模型中定义静态方法来进行过滤。但同一个模型可以与多个管理器一起使用,因此,根据具体情况,可以选择另一个模型。

换句话说,它是模型和视图之间的一层,它以多对一到模型和多对多到视图的方式工作。

我将尝试简要回答您的问题,为其他评论者留下更深入的答案。也没有代码。

这对DRY原则有何帮助?

通常,特别是在较大的项目中,您会有一组在代码中广泛使用的查询。例如,为用户获取购物列表,或者获取一些带有注释字段的帐户元数据。如果将这些查询保存在自定义模型管理器中,您可以:

  • 在一个地方定义它们,并在任何其他地方重复使用
  • 在一个地方修改它们的功能,而不需要关心搜索&修改实际使用管理器方法(查询)的位置

基本上,遵循这一原则(在您的情况下,使用自定义管理器)可以降低您需要操作的代码库的复杂性。

这对代码分割有什么帮助?

所有与查询相关的东西都存在于适当模型的管理器中——您不会在代码库中混淆表示和业务逻辑以及一些实用程序。管理器方法对其使用者一无所知,使用者也不需要了解这些方法的实现。

视图或模型方法不能做的管理者能做什么?

使用管理器,您可以更改返回的查询集,这将是每个使用者的默认更改。此外,谈到管理者与模型,存在语义差异:假设模型的方法专门针对模型实例或与任何模型实例相关的数据进行操作,其中管理者针对任何非特定实体(但属于同一模型)进行操作。把这个想象成";模型方法对表行执行某些操作,而管理器对表行进行某些操作";。

最新更新