【问题标题】:Django - specify which model manager Django admin should useDjango - 指定 Django 管理员应该使用哪个模型管理器
【发布时间】:2010-12-05 10:17:30
【问题描述】:

我为 Django 模型创建了一个自定义管理器,它返回一个包含 objects.all() 子集的 QuerySet。我需要它作为模型的默认管理器,因为我还创建了一个自定义标签,它将从任何模型(由参数指定)中检索内容,并且需要对指定模型使用默认管理器。一切正常,除了 - Django Admin 也使用此特定模型的默认管理器,这意味着并非所有模型实例都出现在 admin 中。

Django 文档没有帮助:

如果您使用自定义 Manager 对象,请注意 Django 遇到的第一个 Manager 对象(在 它们在模型中定义的顺序)具有特殊状态。 Django 将类中定义的第一个 Manager 解释为“默认”Manager,并且 Django 的几个部分(虽然不是管理应用程序)将专门为该模型使用该 Manager。 (Django Managers documentation)

管理员不应该使用默认管理器,但在我看来似乎是这样。请注意,我还明确添加了默认管理器objects

subset = CustomManager() # the default manager
objects = models.Manager() # the one I want admin to use

如何指定管理员应该使用哪个 Manager?

【问题讨论】:

  • 我也被您在管理文档中突出显示的部分绊倒了。这是我发现 django 文档模棱两可的少数几次之一。
  • 奇怪。查看最新的 Django 源代码,管理员似乎确实使用了默认管理器。
  • @Michael 管理员至少从 Django 1.0 开始就使用默认管理器。这里的问题更多是文档错误,已修复 github.com/django/django/commit/…
  • @ChrisLawlor 好点。感谢您的参考:)
  • @Alasdair “这是我发现 django 文档模棱两可的几次 [原文如此] 之一。”哈哈。

标签: python django


【解决方案1】:

您定义经理的顺序很重要。 Admin 获取模型上定义的第一个管理器。

如果你这样做:

subset = CustomManager() # the default manager
objects = models.Manager() # the one I want admin to use

默认管理员为subset

如果你这样做:

objects = models.Manager() # the default manager
subset = CustomManager() # your own manager

那么默认管理器将是objects

【讨论】:

    【解决方案2】:

    由于我们希望 objects 成为唯一的经理,因此管理员将在 self.Admin.manager 中使用 manager

    来自troy.simpson打开的票https://code.djangoproject.com/ticket/4754

    class filterManager(models.Manager):
      def get_query_set(self):
        return super(filterManager, self).get_query_set().filter(name='troy')
    
    class Blah(models.Model):
      name = models.CharField(maxlength=100)
      objects = filterManager()
      class Admin:
        manager = filterManager()
    

    使用 Django 1.11 测试

    【讨论】:

      【解决方案3】:

      您可以通过覆盖 ModelAdmin 子类中的 queryset 方法来选择管理器。

      def get_queryset(self, request):
          # use our manager, rather than the default one
          qs = self.model.objects.get_queryset()
      
          # we need this from the superclass method
          ordering = self.ordering or () # otherwise we might try to *None, which is bad ;)
          if ordering:
              qs = qs.order_by(*ordering)
          return qs
      

      【讨论】:

      • 他们在 Django 1.6 中将该方法重命名为 get_queryset。旧名称现在是deprecated
      • 澄清一下,Telofy 的评论同时适用于queryset()get_query_set()Django 1.6 Release Notes
      【解决方案4】:

      更新代码:

      def get_queryset(self, request):
          """
          Returns a QuerySet of all model instances that can be edited by the
          admin site. This is used by changelist_view.
          """
          qs = self.model._default_manager.get_queryset()
          # TODO: this should be handled by some parameter to the ChangeList.
          ordering = self.get_ordering(request)
          if ordering:
              qs = qs.order_by(*ordering)
          return qs
      

      _default_manager 可以替换...

      【讨论】:

      • 在 Django 1.7.7 上让它工作我不得不用 _base_manager 替换 _default_manager
      猜你喜欢
      • 2021-12-11
      • 1970-01-01
      • 2021-04-05
      • 1970-01-01
      • 2011-01-26
      • 2011-03-12
      • 1970-01-01
      • 2014-07-11
      相关资源
      最近更新 更多