【发布时间】:2011-01-26 18:23:36
【问题描述】:
在出现注册模型的管理站点的根页面,我想隐藏几个注册到 Django admin 的模型。
如果我直接取消注册,我将无法添加新记录,因为添加新符号“+”消失了。
如何做到这一点?
【问题讨论】:
标签: django django-admin
在出现注册模型的管理站点的根页面,我想隐藏几个注册到 Django admin 的模型。
如果我直接取消注册,我将无法添加新记录,因为添加新符号“+”消失了。
如何做到这一点?
【问题讨论】:
标签: django django-admin
适用于 Django 1.8 及更高版本
从 Django 1.8 开始,ModelAdmin 有了一个名为 has_module_permission() 的新方法,它负责在管理索引中显示模型。
要从管理索引中隐藏模型,只需在 ModelAdmin 类中创建此方法并返回 False。示例:
class MyModelAdmin(admin.ModelAdmin):
...
def has_module_permission(self, request):
return False
【讨论】:
has_module_permission 会影响整个应用程序,而不仅仅是一个模型。因此,将此添加到应用程序中的模型会导致应用程序模型列表 (/admin/app_label/) 中出现 403 Forbidden。见django/contrib/admin/sites.py。
return request.path!='/admin/' 之类的方式规避该错误。不幸的是,这会重新启用应用模型列表中的这些模型。
例如,仅不要将 admin.site.register(MyModel, MyModelAdmin) 放在 admin.py 中。正常注册模型。
【讨论】:
从 Django 1.8.18 开始,has_module_permission() 仍然存在问题。所以,在我们的例子中,我们也使用了get_model_perms()。同样,我们只需要为特定用户隐藏模型,但superuser 应该能够访问其索引条目。
class MyModelAdmin(admin.ModelAdmin):
def get_model_perms(self, request):
if not request.user.is_superuser:
return {}
return super(MyModelAdmin, self).get_model_perms(request)
admin.site.register(MyModel, MyModelAdmin)
【讨论】:
我有很多模型管理员要注册和隐藏,如果您想要更 DRY 的解决方案,这对我有用(Django 1.10,Python 3.5)
# admin.py
def register_hidden_models(*model_names):
for m in model_names:
ma = type(
str(m)+'Admin',
(admin.ModelAdmin,),
{
'get_model_perms': lambda self, request: {}
})
admin.site.register(m, ma)
register_hidden_models(MyModel1, MyModel2, MyModel3)
如果您想跨应用重用它,我想您可以将它放入实用程序类中。
【讨论】:
基于x0nix's answer我做了一些实验。似乎从 get_model_perms 返回一个空字典会从 index.html 中排除模型,同时仍然允许您直接编辑实例。
class MyModelAdmin(admin.ModelAdmin):
def get_model_perms(self, request):
"""
Return empty perms dict thus hiding the model from admin index.
"""
return {}
admin.site.register(MyModel, MyModelAdmin)
【讨论】:
get_model_perms = lambda self, req: {}
这是基于 x0nix 答案的替代构建,并且只有当您乐于使用 jquery 隐藏行时。
从其他答案复制粘贴我重复使用的部分
class HiddenModelAdmin(admin.ModelAdmin):
def get_model_perms(self, *args, **kwargs):
perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
perms['list_hide'] = True
return perms
class MyModelAdmin(HiddenModelAdmin):
...
admin.site.register(MyModel, MyModelAdmin)
然后安装django-jquery,然后在您的/admin/index.html模板中添加以下块:
{% extends "admin:admin/index.html" %}
{% block extrahead %}
<script type="text/javascript" src="{{ STATIC_URL }}js/jquery.js"></script>
{% if app_list %}
<script type="text/javascript">
$(function(){
{% for app in app_list %}
{% for model in app.models %}
{% if model.perms.list_hide %}
$('div.app-{{ app.app_label }}').find('tr.model-{{ model.object_name|lower }}').hide();
{% endif %}
{% endfor %}
{% endfor %}
});
</script>
{% endif %}
{% endblock %}
您不需要复制粘贴整个模板,只需扩展它并覆盖extrahead 块。您需要django-apptemplates 才能使上述操作生效。
【讨论】:
Django 1.2 有新的 if 语句,这意味着只有通过覆盖 admin/index.html 才能获得所需的功能
{% if model.name not in "Name of hidden model; Name of other hidden model" %}
...
{% endif %}
这是一个糟糕的解决方案,因为它不关心多语言管理员。您当然可以添加所有受支持语言的模型名称。这是一个很好的解决方案,因为它不会覆盖核心 Django 函数的多个方面。
但在改变任何事情之前,我认为人们应该考虑一下这个......
本质上,问题与不希望使用的模型有关,而不仅仅是偶尔在下拉列表中添加一个选项。它可以通过为“不那么高级”的用户创建一组权限来有效地解决,这些用户在模型太多时会感到恐慌。如果需要更改特定型号,只需使用“高级帐户”登录即可。
【讨论】:
遇到同样的问题,这是我想出的。
像以前的解决方案一样 - 将 index.html 从 django 复制到您的 /admin/index.html 并像这样修改它:
{% for model in app.models %}
{% if not model.perms.list_hide %}
<tr>
...
</tr>
{% endif %}
{% endfor %}
并创建 ModelAdmin 子类:
class HiddenModelAdmin(admin.ModelAdmin):
def get_model_perms(self, *args, **kwargs):
perms = admin.ModelAdmin.get_model_perms(self, *args, **kwargs)
perms['list_hide'] = True
return perms
现在使用 HiddenModelAdmin 子类注册的任何模型都不会显示在管理列表中,但可以通过“加号”详细显示:
class MyModelAdmin(HiddenModelAdmin):
...
admin.site.register(MyModel, MyModelAdmin)
【讨论】:
丑陋的解决方案:override 管理索引模板,即将 django 中的 index.html 复制到 /admin/index.html 并添加如下内容:
{% for for model in app.models %}
{% ifnotequal model.name "NameOfModelToHide" %}
...
【讨论】: