Django - 指定Django管理后台使用哪个模型管理器

44 投票
4 回答
16905 浏览
提问于 2025-04-15 14:57

我为Django模型创建了一个自定义管理器,这个管理器返回一个包含部分对象的查询集(QuerySet),也就是从所有对象中筛选出来的一部分。我需要把这个自定义管理器设为模型的默认管理器,因为我还在创建一个自定义标签,这个标签可以从任何模型中获取内容(通过参数指定),并且需要使用指定模型的默认管理器。到目前为止,这些都运作得很好,唯一的问题是——Django的管理后台也在使用这个特定模型的默认管理器,这就导致并不是所有模型实例都能在管理后台显示出来。

Django的文档没有提供帮助:

如果你使用自定义管理器,请注意Django在模型中遇到的第一个管理器有特殊的地位。Django将这个在类中定义的第一个管理器视为“默认”管理器,Django的多个部分(虽然管理应用除外)将专门使用这个管理器来处理该模型。(Django管理器文档)

管理后台本不应该使用默认管理器,但在我的情况下似乎是这样。请注意,我也明确添加了默认管理器objects

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

我该如何指定管理后台使用哪个管理器呢?

4 个回答

5

你定义管理器的顺序是很重要的。管理员会使用模型中第一个定义的管理器。

所以如果你这样写:

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

12

更新后的代码:

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 可以被替换...

65

你可以通过在你的 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

撰写回答