努力查看自定义 Django 模型管理器的实用程序

Struggling to see the utility of custom Django Model Managers

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

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

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

class ActiveManager(models.Manager):

    def get_queryset(self, *args, **kwargs):
        return super().get_queryset(*args, **kwargs).filter(
            <strong>active=True</strong>
        )

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

class MyActiveModel(models.Model):
    <strong>active</strong> = models.BooleanField(default=False)

    <strong>objects = ActiveManager()</strong>

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

如果您想对查询集进行扩展,也经常使用 Manager

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

class AuthorQuerySet(models.QuerySet):

    def from_user(self, user):
        if user<strong>.is_superuser</strong>:
            return self
        else:
            return self<strong>.filter(author=user)</strong>

然后与允许进行此过滤的经理合作:

from django.conf import settings

class Post(models.Model):
    <strong>author</strong> = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )

    objects = AuthorQuerySet<strong>.as_manager()</strong>

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

Post.objects<strong>.filter_user(myuser)</strong>

或在过滤器链中执行此操作:

Post.objects.filter(title__istartswith='The').<strong>filter_user(myuser)</strong>

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

How does this help with code segmentation?

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

What can managers do that views or model methods cannot do?

每个视图可以重复一次相同的过滤代码,但这使得以后很难在流程中更改该逻辑,因为那时应该查看访问这些模型的视图,并对 全部 这些观点。这会很容易忽略某些东西,从而导致状态不一致。

也可以在模型中定义静态方法来进行过滤。但同一个模型可以与 多个 经理一起工作,因此,根据情况,选择另一个模型。

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

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

How does this help with DRY principles?

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

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

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

How does this help with code segmentation?

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

What can managers do that views or model methods cannot do?

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