django admin在修改obj时使字段为只读,但在添加新的obj时需要

在pipe理员中,我想在修改对象时禁用一个字段,但在添加新对象时使其成为必需。

什么Django的方式去这个?

您可以覆盖pipe理员的get_readonly_fields方法:

 class MyModelAdmin(admin.ModelAdmin): def get_readonly_fields(self, request, obj=None): if obj: # editing an existing object return self.readonly_fields + ('field1', 'field2') return self.readonly_fields 

供参考:如果有人遇到了我遇到的两个相同的问题:

  1. 您应该仍然在类的主体中声明任何永久readonly_fields,因为将从validation中访问readonly_fields类属性(请参阅django.contrib.admin.validation:validate_base(),line.213 appx)

  2. 这不会与Inline一起工作,因为传递给get_readonly_fields()的obj是父obj(我有两个使用css或js的hacky和low-security解决scheme)

如果要将所有字段设置为只读在更改视图上,请覆盖admin的get_readonly_fields:

 def get_readonly_fields(self, request, obj=None): if obj: # editing an existing object # All model fields as read_only return self.readonly_fields + tuple([item.name for item in obj._meta.fields]) return self.readonly_fields 

如果你想在更改视图上隐藏保存button

  1. 改变视图

     def change_view(self, request, object_id, form_url='', extra_context=None): ''' customize edit form ''' extra_context = extra_context or {} extra_context['show_save_and_continue'] = False extra_context['show_save'] = False extra_context['show_save_and_add_another'] = False # this not works if has_add_permision is True return super(TransferAdmin, self).change_view(request, object_id, extra_context=extra_context) 
  2. 如果用户正在尝试编辑,请更改权限:

     def has_add_permission(self, request, obj=None): # Not too much elegant but works to hide show_save_and_add_another button if '/change/' in str(request): return False return True 

    这个解决scheme已经通过Django 1.11进行了testing

你可以通过覆盖ModelAdmin的formfield_for_foreignkey方法来做到这一点:

 from django import forms from django.contrib import admin from yourproject.yourapp.models import YourModel class YourModelAdmin(admin.ModelAdmin): class Meta: model = YourModel def formfield_for_foreignkey(self, db_field, request=None, **kwargs): # Name of your field here if db_field.name == 'add_only': if request: add_opts = (self._meta.app_label, self._meta.module_name) add = u'/admin/%s/%s/add/' % add_opts if request.META['PATH_INFO'] == add: field = db_field.formfield(**kwargs) else: kwargs['widget'] = forms.HiddenInput() field = db_field.formfield(**kwargs) return field return admin.ModelAdmin(self, db_field, request, **kwargs) 

有类似的问题。 我用ModelAdmin中的“add_fieldsets”和“restricted_fieldsets”解决了这个问题。

 from django.contrib import admin class MyAdmin(admin.ModelAdmin): declared_fieldsets = None restricted_fieldsets = ( (None, {'fields': ('mod_obj1', 'mod_obj2')}), ( 'Text', {'fields': ('mod_obj3', 'mod_obj4',)}), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('add_obj1', 'add_obj2', )}), ) 

请参阅: http : //code.djangoproject.com/svn/django/trunk/django/contrib/auth/admin.py

但是这并不能保护您的模型免受“add_objX”的后续更改。 如果你也想这样,我认为你必须去模型类“保存”function的方式,并检查在那里的变化。

请参阅:www.djangoproject.com/documentation/models/save_delete_hooks/

Greez,尼克

基于之前Bernhard Vallant的出色build议,也保留了基类(如果有的话)提供的任何可能的定制:

 class MyModelAdmin(BaseModelAdmin): def get_readonly_fields(self, request, obj=None): readonly_fields = super(MyModelAdmin, self).get_readonly_fields(request, obj) if obj: # editing an existing object return readonly_fields + ['field1', ..] return readonly_fields