覆盖Django admin中的默认查询集

覆盖Django admin中的默认查询集,django,django-models,django-admin,Django,Django Models,Django Admin,我的一个模型具有“已删除”标志,用于全局隐藏对象: class NondeletedManager(models.Manager): """Returns only objects which haven't been deleted""" def get_query_set(self): return super(NondeletedManager, self).get_query_set().exclude(deleted=True) class Conv

我的一个模型具有“已删除”标志,用于全局隐藏对象:

class NondeletedManager(models.Manager):
    """Returns only objects which haven't been deleted"""

    def get_query_set(self):
        return super(NondeletedManager, self).get_query_set().exclude(deleted=True)

class Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)
    objects = NondeletedManager()
    all_conversations = models.Manager() # includes deleted conversations

如何覆盖Django管理模块使用的默认queryset以包含已删除的对话?

以下内容有什么问题:

class Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)
    objects = models.Manager() # includes deleted conversations
    nondeleted_conversations = NondeletedManager()
因此,在您自己的应用程序/项目中,您可以使用
Conversation.nondeleted_conversations()
,并让内置的管理应用程序完成它的工作。

您可以
在模型管理类中获取\u queryset
方法

class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super(MyModelAdmin, self).get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)

注:在Django中,Konrad是正确的,但这比文档中给出的示例更困难

已删除的对话不能包含在已排除它们的查询集中。因此,除了完全重新实现admin.ModelAdmin.queryset之外,我看不到其他选项

class ConversationAdmin (admin.ModelAdmin):

    def queryset (self, request):
        qs = Conversation.all_conversations
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs

接受的解决方案对我来说非常有用,但我需要多一点灵活性,因此我最终扩展了changelist视图,添加了一个自定义queryset参数。我现在可以配置默认的queryset/filter,并且仍然可以使用不同的筛选器(获取参数)对其进行修改:


你可以用Django做这个

或者,如果您有一个要重用的现有ModelAdmin类:

admin.site.register(UnfilteredConversation, ConversationAdmin)

这种方法避免了在原始对话模型上覆盖默认管理器时可能出现的问题,因为默认管理器也用于许多关系和反向ForeignKey关系。

Natan Yellin是正确的,但您可以更改管理器顺序,第一个将是默认的,然后是管理员使用的:

class Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)

    all_conversations = models.Manager() # includes deleted conversations
    objects = NondeletedManager()
get\u queryset()
的管理实现使用
\u default\u manager
代替
.objects
,如下所示

qs = self.model._default_manager.get_queryset()
参考号


这只会确保每次使用Model.objects时,都不会包含已删除的对象,而是通用视图和其他视图使用的对象。_default_manager。那么,如果不重写get_queryset,那么它就不是一个解决方案。我刚刚检查了ListView和admin。

对于那些简单的查询,您真的需要自定义管理器吗?是的,删除的对象应该被普遍忽略(除了在admin页面上),因此设置默认值是有意义的。除了admin页面之外,我在任何地方都忽略删除的对象,所以我认为这应该是默认值。此外,通过这种方式,我不需要通过添加删除对话的功能来更新遗留代码。在这种情况下该如何工作?我是否可以修改由
ModelAdmin.queryset
创建的queryset以包含已删除的对象?我不想自己构建queryset而不是调用超类。看看我的答案,看看我的意思。除了完全重新实现该功能外,还有其他方法吗?它有助于将答案实际放入答案中,而不仅仅是链接。该链接现在已失效,因此我将更新以给出解释。在Django 1.6上,转到
get\u queryset
。我无法使其正常工作。我得到一个错误,说。过滤器是没有在qs对象。第二,除了请求之外,我也不能使用queryset。有什么帮助吗?我不认为这有什么问题。使用两个管理者是一种方法。然而,Django管理员确实可以提供一个钩子,这样您就不必重新实现订购部分。
class Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)

    all_conversations = models.Manager() # includes deleted conversations
    objects = NondeletedManager()
qs = self.model._default_manager.get_queryset()