在Django admin中覆盖默认查询集

时间:2012-09-10 14:46:13

标签: 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

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

5 个答案:

答案 0 :(得分:110)

您可以在模型管理类中使用override 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)

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

答案 1 :(得分:7)

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

答案 2 :(得分:2)

以下内容会出现什么问题:

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

因此,在您自己的应用/项目中,您使用Conversation.nondeleted_conversations()并让内置管理应用程序执行此操作。

答案 3 :(得分:2)

接受的解决方案对我很有用,但我需要更多的灵活性,所以我最终扩展了changelist视图以添加自定义queryset参数。我现在可以配置我的默认查询集/过滤器,它仍然可以使用不同的过滤器(获取参数)进行修改:

def changelist_view(self, request, extra_context=None):
    if len(request.GET) == 0 :
        q = request.GET.copy()
        q['status__gt'] = 4
        request.GET = q
        request.META['QUERY_STRING'] = request.GET.urlencode()

    return super(WorksheetAdmin,self).changelist_view(request, extra_context=extra_context)

答案 4 :(得分:0)

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

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

    all_conversations = models.Manager() # includes deleted conversations
    objects = NondeletedManager()

get_queryset()的管理员实现使用._default_manager代替.objects,如下所示

qs = self.model._default_manager.get_queryset()

ref Django github BaseModelAdmin implementation

这仅确保每次您使用YourModel.objects时,都不会包括已删除的对象,但是常规视图和其他视图也都使用._default_manager。然后,如果不重写,则get_queryset不是解决方案。我只是检查了ListView和管理员。