如何在管理界面中使模型完全只读?这是针对一种日志表的情况,我使用管理功能进行搜索、排序、过滤等操作,但没有必要修改日志。
如果看起来像一个重复的问题,那么这不是我想做的:
- 我不是在寻找只读字段(即使将每个字段设为只读,仍然可以创建新记录)
- 我不是在创建只读用户:每个用户都应该是只读的。
如何在管理界面中使模型完全只读?这是针对一种日志表的情况,我使用管理功能进行搜索、排序、过滤等操作,但没有必要修改日志。
如果看起来像一个重复的问题,那么这不是我想做的:
class MyAdmin(ModelAdmin):
def has_add_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
readonly_fields = [field.name for field in MyModel._meta.get_fields()]
这里有两个类,我正在使用它们来使模型及其内联变成只读。
对于模型管理:
from django.contrib import admin
class ReadOnlyAdmin(admin.ModelAdmin):
readonly_fields = []
def get_readonly_fields(self, request, obj=None):
return list(self.readonly_fields) + \
[field.name for field in obj._meta.fields] + \
[field.name for field in obj._meta.many_to_many]
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
class MyModelAdmin(ReadOnlyAdmin):
pass
对于内联元素:
class ReadOnlyTabularInline(admin.TabularInline):
extra = 0
can_delete = False
editable_fields = []
readonly_fields = []
exclude = []
def get_readonly_fields(self, request, obj=None):
return list(self.readonly_fields) + \
[field.name for field in self.model._meta.fields
if field.name not in self.editable_fields and
field.name not in self.exclude]
def has_add_permission(self, request):
return False
class MyInline(ReadOnlyTabularInline):
pass
ReadOnlyAdmin
中的 has_add_permission
方法只接受请求参数。 - MartinM参见https://djangosnippets.org/snippets/10539/
class ReadOnlyAdminMixin(object):
"""Disables all editing capabilities."""
change_form_template = "admin/view.html"
def __init__(self, *args, **kwargs):
super(ReadOnlyAdminMixin, self).__init__(*args, **kwargs)
self.readonly_fields = [f.name for f in self.model._meta.get_fields()]
def get_actions(self, request):
actions = super(ReadOnlyAdminMixin, self).get_actions(request)
del_action = "delete_selected"
if del_action in actions:
del actions[del_action]
return actions
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
def save_model(self, request, obj, form, change):
pass
def delete_model(self, request, obj):
pass
def save_related(self, request, form, formsets, change):
pass
模板/管理员/视图.html
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block submit_buttons_bottom %}
<div class="submit-row">
<a href="../">{% blocktrans %}Back to list{% endblocktrans %}</a>
</div>
{% endblock %}
模板/admin/view.html(适用于Grappelli)
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block submit_buttons_bottom %}
<footer class="grp-module grp-submit-row grp-fixed-footer">
<header style="display:none"><h1>{% trans "submit options"|capfirst context "heading" %}</h1></header>
<ul>
<li><a href="../" class="grp-button grp-default">{% blocktrans %}Back to list{% endblocktrans %}</a></li>
</ul>
</footer>
{% endblock %}
Model
还是为 ModelAdmin
编写的 mixin? - OrangeDogModelAdmin
设计的。 - Pascal Polleunusclass ReadOnlyAdminMixin:
def has_add_permission(self, request):
return False
def has_change_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
class LogEntryAdmin(ReadOnlyAdminMixin, admin.ModelAdmin):
list_display = ('id', 'user', 'action_flag', 'content_type', 'object_repr')
如果您想让用户知道他/她无法编辑它,第一个解决方案缺少两个要素。您需要删除“删除”操作!
class MyAdmin(ModelAdmin)
def has_add_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
def get_actions(self, request):
actions = super(MyAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
第二点:对于普通模型,只读解决方案可行。但如果您使用具有外键的继承模型,则不可行。不幸的是,我目前还不知道解决方法。一个不错的尝试是:
但这对我也不起作用。
最后需要注意的是,如果您想考虑一个广泛的解决方案,您必须强制每个内联也是只读的。
这是在 Django 2.1 中添加的功能,发布日期为 2018 年 8 月 1 日!
ModelAdmin.has_view_permission()
与现有的 has_delete_permission、has_change_permission 和 has_add_permission 类似。您可以在文档中阅读有关它的信息。
来自版本说明:
这使得用户可以以只读方式访问管理中的模型。 ModelAdmin.has_view_permission() 是新功能。实现向后兼容,因为无需分配“查看”权限即可允许具有“更改”权限的用户编辑对象。
实际上,您可以尝试这个简单的解决方案:
class ReadOnlyModelAdmin(admin.ModelAdmin):
actions = None
list_display_links = None
# more stuff here
def has_add_permission(self, request):
return False
actions = None
: 避免显示带有“删除所选...”选项的下拉菜单list_display_links = None
: 避免在列中单击以编辑对象has_add_permission()
返回False可避免为该模型创建新对象如果被接受的答案对你无效,请尝试以下方法:
def get_readonly_fields(self, request, obj=None):
readonly_fields = []
for field in self.model._meta.fields:
readonly_fields.append(field.name)
return readonly_fields
结合@darklow和@josir的优秀回答,并添加一些内容以删除“保存”和“保存并继续”按钮,得到以下代码(使用Python 3语法):
class ReadOnlyAdmin(admin.ModelAdmin):
"""Provides a read-only view of a model in Django admin."""
readonly_fields = []
def change_view(self, request, object_id, extra_context=None):
""" customize add/edit form to remove save / save and continue """
extra_context = extra_context or {}
extra_context['show_save_and_continue'] = False
extra_context['show_save'] = False
return super().change_view(request, object_id, extra_context=extra_context)
def get_actions(self, request):
actions = super().get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def get_readonly_fields(self, request, obj=None):
return list(self.readonly_fields) + \
[field.name for field in obj._meta.fields] + \
[field.name for field in obj._meta.many_to_many]
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
然后你就可以像这样使用
class MyModelAdmin(ReadOnlyAdmin):
pass
我只在Django 1.11 / Python 3上尝试过这个功能。
使用Django 2.2,我可以这样做:
@admin.register(MyModel)
class MyAdmin(admin.ModelAdmin):
readonly_fields = ('all', 'the', 'necessary', 'fields')
actions = None # Removes the default delete action in list view
def has_add_permission(self, request):
return False
def has_change_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return False
readonly_fields
和actions
行不是必需的。 - cheng10
has_view_permission
在 Django 2.1 中终于得到了实现。另请参见下面的 https://dev59.com/emsy5IYBdhLWcg3w3hyI#51641149。 - djvg