在Djangopipe理界面的只读模型?

如何在pipe理界面中使模型完全只读? 这是一种日志表,我使用的pipe理function来search,sorting,过滤等,但没有必要修改日志。

如果这看起来像一个重复的,这不是我想要做的:

  • 我不寻找只读字段 (即使每个字段只读,仍然可以让你创build新的logging)
  • 我不想创build一个只读用户 :每个用户应该只读。

请参阅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 = self.model._meta.get_all_field_names() def get_actions(self, request): actions = super(ReadOnlyAdminMixin, self).get_actions(request) del actions["delete_selected"] 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 

模板/pipe理/ view.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 %} 

templates / 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 %} 

pipe理员是为了编辑,而不仅仅是查看(你不会find一个“查看”权限)。 为了实现你想要的,你必须禁止添加,删除,并使所有字段只读:

 class MyAdmin(ModelAdmin): def has_add_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False 

(如果你禁止改变你甚至不会看到对象)

对于一些试图自动设置所有字段的未经testing的代码,只读看到我对整个模型的答案是只读的

编辑:也未经testing,但只是看看我的LogEntryAdmin,它有

 readonly_fields = MyModel._meta.get_all_field_names() 

不知道这是否会在所有情况下工作。

编辑:QuerySet.delete()可能仍然批量删除对象。 为了解决这个问题,请提供您自己的“对象”pipe理器和相应的不删除的QuerySet子类 – 请参阅在Django中重写QuerySet.delete()

这里有两个我用来制作模型和/或只读内联的类。

对于模特pipe理员:

 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 

如果您希望用户意识到他/她无法编辑它,则第一个解决scheme中会丢失2个部分。 您已删除删除操作!

 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 

第二:readonly解决scheme在普通模型上工作正常。 但是,如果你有一个外键的inheritance模型,这是行不通的。 不幸的是,我还不知道这个解决scheme。 一个好的尝试是:

整个模型只读

但是这对我也不起作用。

最后一点,如果你想考虑一个广泛的解决scheme,你必须强制每个内联必须是只读的。

如果接受的答案不适合你,请试试这个:

 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 

其实你可以试试这个简单的解决scheme:

 class ReadOnlyModelAdmin(admin.ModelAdmin): actions = None list_display_links = None # more stuff here def has_add_permission(self, request): return False 
  • actions = None :避免使用“Delete selected …”选项显示下拉菜单
  • list_display_links = None :避免点击列来编辑该对象
  • has_add_permission()返回False避免为该模型创build新的对象

接受的答案应该可以工作,但是这也将保持只读字段的显示顺序。 您也不必使用此解决scheme对模型进行硬编码。

 class ReadonlyAdmin(admin.ModelAdmin): def __init__(self, model, admin_site): super(ReadonlyAdmin, self).__init__(model, admin_site) self.readonly_fields = [field.name for field in filter(lambda f: not f.auto_created, model._meta.fields)] def has_delete_permission(self, request, obj=None): return False def has_add_permission(self, request, obj=None): return False 

编译@darklow和@josir的优秀答案,加上更多的删除“保存”和“保存并继续”button导致(在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 admin中的某些用户只读取所有字段时,我遇到了相同的需求,最终利用django模块“django-admin-view-permission”而无需滚动自己的代码。 如果您需要更细粒度的控制来显式定义哪些字段,则需要扩展该模块。 你可以在这里查看这个插件