在Django admin中覆盖默认查询集

Nat*_*lin 64 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 Conversation(BaseModel):
    ...
    deleted = models.BooleanField(default=False)
    objects = NondeletedManager()
    all_conversations = models.Manager() # includes deleted conversations
Run Code Online (Sandbox Code Playgroud)

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

Kon*_*łas 117

您可以在模型管理类中覆盖 get_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)
Run Code Online (Sandbox Code Playgroud)

注意在Django <= 1.5中,该方法仅被命名queryset.

  • 在Django 1.6上,[此方法被重命名](https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset)改为`get_queryset`. (14认同)
  • 它有助于实际将答案放在你的答案中,而不仅仅是链接.这个链接现在已经死了,所以我会更新以解释. (4认同)
  • 在这种情况下,它会如何工作?我可以修改`ModelAdmin.queryset`创建的查询集以包含已删除的对象吗?我不想自己构建查询集而不是调用超类. (2认同)

Nat*_*lin 8

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
Run Code Online (Sandbox Code Playgroud)


zlo*_*ady 7

您可以使用 Django代理模型来完成此操作。

# models.py
class UnfilteredConversation(Conversation):
    class Meta:
        proxy = True

    # this will be the 'default manager' used in the Admin, and elsewhere
    objects = models.Manager() 

# admin.py
@admin.register(UnfilteredConversation)
class UnfilteredConversationAdmin(Conversation):
    # regular ModelAdmin stuff here
    ...
Run Code Online (Sandbox Code Playgroud)

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

admin.site.register(UnfilteredConversation, ConversationAdmin)
Run Code Online (Sandbox Code Playgroud)

此方法避免了覆盖原始会话模型上的默认管理器可能出现的问题 - 因为默认管理器也用于多对多关系和反向外键关系。