【问题标题】:Django admin: What is the best way to add a custom list view?Django admin:添加自定义列表视图的最佳方法是什么?
【发布时间】:2010-12-26 15:06:57
【问题描述】:

我想在管理中提供一个与changelist_view() 非常相似的自定义视图,但没有指向编辑表单视图的链接。用户将能够像在更改列表表单中一样选择列表中的项目并应用操作,但他们无权访问编辑表单。

我觉得ModelAdmin类中的结构应该是这样的:

class ProductAdmin(admin.ModelAdmin):
    def get_urls(self):
        urls = super(ProductAdmin, self).get_urls()
        urls += patterns('',
            (r'^selectlist/$', self.selectlist_view)
        )
        return urls

    def selectlist_view(self):
        return render_to_response(...)

要返回的视图与ModelAdmin.changelist_view() 非常相似。执行此操作的最佳且干燥的方法是什么?

【问题讨论】:

    标签: python django django-admin custom-view


    【解决方案1】:

    以下自定义 ModelAdmin 是迄今为止我能想到的最佳解决方案:

    class UserModelAdmin(ModelAdmin):
        def get_urls(self):
            urls = super(UserModelAdmin, self).get_urls()
            info = self.model._meta.app_label, self.model._meta.module_name
            select_list_url = patterns('',
                url(r'^selectlist/$', self.selectlist_view, 
                    name='%s_%s_select' % info)
            )
            return select_list_url + urls
    
        def selectlist_view(self, request, extra_context=None):
            temp_list_display_links = self.list_display_links
            self.list_display_links = (None, )
            response = self.changelist_view(request, extra_context)
            self.list_display_links = temp_list_display_links
            return response
    

    【讨论】:

    • 编辑问题比回答自己的问题要好。 :-)
    • 这是我想出并有效的解决方案。所以感觉就像是对我的回答:)
    • 它让别人更容易回答你的问题,因为问题总是显示在界面顶部(而不是答案)。
    • @PauloScardine it's perfectly OK for people to answer their own question 而不是将他们的答案嵌入到问题中。
    • @GregoryGoltsov:我没有说别的。我认为编辑问题以嵌入答案使它成为一个更好的问题,每个人都可以投票以奖励作者;如果我支持他的回答,他将不会受益。但这只是我的意见,这就是为什么评论对此微笑。 :-)
    【解决方案2】:

    我真的不知道为什么,但我个人倾向于 override (or extend) the change list template 用于特定模型,而不是猴子修补 ModelAdmin。

    编辑:

    谢谢,但我需要自定义,这无法通过覆盖模板来完成。例如显示不同的查询集等。

    为了显示不同的查询集,您可以覆盖 ModelAdmin.queryset()。

    也不应该能够编辑列出的项目。如果我覆盖模板,用户将看不到编辑表单的链接,但如果他能猜出表单的 url,他仍然可以访问表单并通过键入 url 来编辑它,这将是一个安全漏洞。

    为什么不直接删除相关用户的编辑权限?您也可以覆盖“添加”和“更改”视图:

    class SomeModelAdmin(admin.ModelAdmin):
        ...
        def change_view(self, request, object_id, extra_context=None):
            return render_to_response('forbiden_operation.html', dict(op='edit'))
        def ModelAdmin.add_view(self, request, form_url='', extra_context=None):
            return render_to_response('forbiden_operation.html', dict(op='add'))
    

    这些是“官方”挂钩,未来不太可能中断。

    还记得《管理之禅》:

    本质上,Django 的管理界面是为单个活动设计的:

    受信任的用户编辑结构化内容。

    是的,它非常简单——但这种简单性是基于大量假设的。 Django 管理界面的整个哲学直接来自这些假设,所以让我们在接下来的部分中深入研究这个短语的潜台词。 “值得信赖的用户……”

    管理界面旨在供您(开发人员)信任的人使用。这不仅仅意味着“经过身份验证的人”;这意味着 Django 假设您的内容编辑器可以被信任做正确的事情。

    这反过来意味着编辑内容没有审批流程 - 如果您信任您的用户,没有人需要批准他们的编辑。另一个含义是权限系统虽然功能强大,但在撰写本文时不支持基于每个对象限制访问。如果您相信某人可以编辑他或她自己的故事,那么您就相信该用户不会在未经许可的情况下编辑其他任何人的故事。

    “……编辑……”

    Django 管理界面的主要目的是让人们编辑数据。起初这似乎很明显,但它再次产生了一些微妙而强大的影响。

    例如,尽管管理界面对于查看数据非常有用(如前所述),但在设计时并未考虑到该目的。例如,请注意缺少“可以查看”权限(参见第 12 章)。 Django 假设如果允许人们在管理界面中查看内容,他们也可以编辑它。

    另一个需要注意的更重要的事情是,即使是远程接近“工作流程”,也没有任何东西。如果给定任务需要一系列步骤,则不支持强制以任何特定顺序完成这些步骤。 Django 的管理界面专注于编辑,而不是围绕编辑的活动。这种对工作流的回避也源于信任原则:管理界面的理念是工作流是人事问题,而不是要在代码中实现的东西。

    最后,请注意管理界面中缺少聚合。也就是说,不支持显示总数、平均值等。同样,管理界面用于编辑——预计您将为所有其余部分编写自定义视图。

    “……结构化内容”

    与 Django 的其他部分一样,管理界面希望您使用结构化数据。因此,它只支持编辑存储在 Django 模型中的数据;对于其他任何东西,例如存储在文件系统上的数据,您都需要自定义视图。

    句号

    现在应该很清楚 Django 的管理界面并没有尝试对所有人都适用;相反,我们选择专注于一件事并把那件事做得非常好。

    当谈到扩展 Django 的管理界面时,许多相同的理念都成立(请注意,“可扩展性”在我们的目标中没有出现)。因为自定义 Django 视图可以做任何事情,并且因为它们可以很容易地在视觉上集成到管理界面中(如下一节所述),所以自定义管理界面的内置机会在一定程度上受到设计的限制。

    您应该记住,管理界面“只是一个应用程序”,尽管它非常复杂。它不会做任何有足够时间的 Django 开发人员无法重现的事情。将来完全有可能有人会开发一个基于不同假设集的不同管理界面,因此会有不同的行为。

    最后,我们应该指出,在撰写本文时,Django 开发人员正在开发一个新版本的管理界面,该界面允许更大的自定义灵活性。当您阅读本文时,这些新功能可能已经进入了真正的 Django 发行版。要找出答案,请询问 Django 社区中的某个人是否集成了“newforms-admin”分支。

    为了在自定义方面提供更大的灵活性,管理应用已经看到了很多改进,但恕我直言,“管理之禅”的大部分内容仍然适用。

    【讨论】:

    • 谢谢,但我需要自定义,这无法通过覆盖模板来完成。例如显示不同的查询集等,也不应该能够编辑列出的项目。如果我覆盖模板,用户将看不到编辑表单的链接,但如果他能猜出表单的 url,他仍然可以访问表单并通过键入 url 来编辑它,这将是一个安全漏洞。
    • 覆盖 ModelAdmin.queryset() 是不够的,因为我需要不同视图上的不同查询集。例如,用户将只能在更改列表中看到他的产品并能够对其进行编辑。但在选择列表视图中,他将看到所有产品,并且能够选择并添加一些产品到他的产品组合中,但不能编辑它们。对于第二部分,如果我删除 can_change 权限,用户将在管理员的任何部分都看不到更改列表。这些当然可以调整,但我正在寻找的是最干燥的方式,定义一个新的视图仍然感觉更自然。
    • @omat:我的意思是,为每个需要自定义行为的基于 ModelAdmin 的类覆盖查询集;也就是说,这种工作流程迟早会变得对 django 管理员来说太大了 - 有时滚动自定义界面比扭曲管理应用程序更容易。
    猜你喜欢
    • 1970-01-01
    • 2016-08-11
    • 2010-10-22
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2012-02-27
    相关资源
    最近更新 更多