有没有办法在django admin中创建只读模型?但我的意思是整个模型。 那么,没有添加,没有删除,没有变化,只看到对象和字段,一切都是只读的?
答案 0 :(得分:11)
ModelAdmin提供了钩子get_readonly_fields() - 以下是未经测试的,我的想法是以ModelAdmin的方式确定所有字段,而不用自己的readonly字段进行递归:
from django.contrib.admin.util import flatten_fieldsets
class ReadOnlyAdmin(ModelAdmin):
def get_readonly_fields(self, request, obj=None):
if self.declared_fieldsets:
fields = flatten_fieldsets(self.declared_fieldsets)
else:
form = self.get_formset(request, obj).form
fields = form.base_fields.keys()
return fields
然后继承子类/ mixin这个管理员应该是一个只读的管理员。
对于添加/删除,并使其按钮消失,您可能还想添加
def has_add_permission(self, request):
# Nobody is allowed to add
return False
def has_delete_permission(self, request, obj=None):
# Nobody is allowed to delete
return False
P.S。:在ModelAdmin中,如果has_change_permission(查找或您的覆盖)返回False,则不会进入对象的更改视图 - 甚至不会显示指向它的链接。如果它确实很酷,并且默认的get_readonly_fields()检查了更改权限并在这种情况下将所有字段设置为只读,如上所述。这样非变换者至少可以浏览数据......鉴于当前的管理结构假设view = edit,正如jathanism指出的那样,这可能需要在添加/更改/删除之上引入“查看”权限...
编辑:关于设置所有字段只读,也未经测试但看起来很有希望:
readonly_fields = MyModel._meta.get_all_field_names()
编辑:这是另一个
if self.declared_fieldsets:
return flatten_fieldsets(self.declared_fieldsets)
else:
return list(set(
[field.name for field in self.opts.local_fields] +
[field.name for field in self.opts.local_many_to_many]
))
答案 1 :(得分:3)
As"查看权限"不幸的是,will not make it into Django 1.11是一个解决方案,使您的ModelAdmin 只读同时进行保存模型更改和添加模型历史记录日志条目 a no-op
def false(*args, **kwargs):
"""A simple no-op function to make our changes below readable."""
return False
class MyModelReadOnlyAdmin(admin.ModelAdmin):
list_display = [
# list your admin listview entries here (as usual)
]
readonly_fields = [
# list your read-only fields here (as usual)
]
actions = None
has_add_permission = false
has_delete_permission = false
log_change = false
message_user = false
save_model = false
(注意:不要将false
无操作助手误认为内置False
。如果您不同情辅助功能在课外,将其调入课堂,称之为no_op
或其他内容,或通过def
s覆盖受影响的属性。减少干,但如果你不在乎......)
这将:
它不会:
请注意,get_all_field_names
(如接受的答案中所述)为removed in Django 1.10。
用Django 1.10.5测试。
答案 2 :(得分:2)
您可以使用readonly_fields
属性自定义ModelAdmin
个班级。有关详情,请参阅this answer。
答案 3 :(得分:1)
选择的答案不适用于Django 1.11,并且我发现了一种更简单的方法,因此我想与您分享:
class MyModelAdmin(admin.ModelAdmin):
def get_readonly_fields(self, request, obj=None):
return [f.name for f in obj._meta.fields]
def has_delete_permission(self, request, obj=None):
return False
def has_add_permission(self, request):
return False
答案 4 :(得分:0)
我有类似的情况:
因为可以覆盖ModelAdmin中的change_view()
,我们可以利用它来阻止模型实例创建后的编辑。这是我用过的一个例子:
def change_view(self, request, object_id, form_url='', extra_context=None):
messages.error(request, 'Sorry, but editing is NOT ALLOWED')
return redirect(request.META['HTTP_REFERER'])
我也意识到文档以不同的方式解释ModelAdmin.has_change_permission()
的结果:
如果允许编辑obj,则返回True,否则返回False。如果 obj为None,应返回True或False以指示是否编辑 通常允许这种类型的对象(例如,False将是 解释为意味着不允许当前用户编辑 任何此类对象)。
意思是我可以检查obj
是否None
,在这种情况下我返回True
,否则我返回False
,这实际上允许用户查看更改-list,但在保存模型实例后无法编辑或查看change_form。
def has_change_permission(self, request, obj = None, **kwargs):
if obj is None:
return True
else:
return False
虽然我认为这也可能会覆盖任何MODEL_can_change
权限,允许不受欢迎的眼睛查看更改列表?
答案 5 :(得分:-1)
根据我对Django 1.8的测试,我们不能按照答案#3中的说明使用以下内容,但它适用于Django 1.4:
## self.get_formset(request, obj) ##
answer 3 needs fix. Generally, alternative codes for this issue about below section
## form = self.get_formset(request, obj).form ##
## fields = form.base_fields.keys() ##
可以是:
#~ (A) or
[f.name for f in self.model._meta.fields]
#~ (B) or
MyModel._meta.get_all_field_names()
#~ (C)
list(set([field.name for field in self.opts.local_fields] +
[field.name for field in self.opts.local_many_to_many]
))