2

我想在管理员中提供一个与 非常相似的自定义视图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()。什么是最好的和干燥的方法来做到这一点?

4

2 回答 2

4

以下自定义 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
于 2010-12-26T17:20:30.097 回答
3

我真的不知道为什么,但我个人倾向于覆盖(或扩展)特定模型的更改列表模板,而不是monkeypatching 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 管理界面的整个哲学直接来自这些假设,所以让我们在接下来的部分中深入研究这个短语的潜台词。“值得信赖的用户……”</p>

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

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

“……编辑……”</p>

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

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

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

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

“……结构化内容”</p>

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

句号

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

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

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

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

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

于 2010-12-26T22:35:57.690 回答