In admin I would like to disable a field when modifying object, but make it required when adding new object.
在admin中,我希望在修改对象时禁用字段,但是在添加新对象时需要禁用字段。
Whats the django way to go about this one?
这个《被解救的姜戈》怎么说?
6 个解决方案
#1
130
You can override the admin's get_readonly_fields
method:
您可以覆盖管理员的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
#2
7
If you want to set all fields as read only just on the change view, override the admin's get_readonly_fields:
如果您希望将所有字段设置为仅在change视图上读取,请重写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
And if you want to hide save buttons on change view:
如果你想在更改视图中隐藏保存按钮:
-
Change the view
改变了观点
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)
-
Change permissions if user is trying to edit:
如果用户正在尝试编辑,请更改权限:
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
This solution has been tested over Django 1.11
这个解决方案已经在Django 1.11上进行了测试
#3
3
FYI: in case someone else runs into the same two problems I encountered:
供参考:如果有人遇到了我遇到的两个问题:
-
You should still declare any permanently readonly_fields in the body of the class, as the readonly_fields class attribute will be accessed from validation (see django.contrib.admin.validation: validate_base(), line.213 appx)
您仍然应该在类的主体中声明任何永久性的readonly_fields,因为从验证中将访问readonly_fields类属性(参见django.后悔.admin)。验证:validate_base()。213附录)
-
This won't work with Inlines as the obj passed to get_readonly_fields() is the parent obj (I have two rather hacky and low-security solutions using css or js)
由于传递给get_readonly_fields()的obj是obj的父类(我有两个使用css或js的相当陈腐和低安全性的解决方案),所以这对inline是不起作用的。
#4
0
You can do this by overriding the formfield_for_foreignkey method of the ModelAdmin:
可以通过重写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)
#5
0
Got a similar problem. I solved it with "add_fieldsets" and "restricted_fieldsets" in the ModelAdmin.
有一个类似的问题。我在ModelAdmin中使用“add_fieldsets”和“restricted ted_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', )}),
)
Please see e.g.: http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/admin.py
请见如:http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/admin.py
But this doesn't protect your model from later changes of "add_objX". If you want this too, I think you have to go the way over the Model class "save" function and check for changes there.
但是这并不能保护您的模型不受以后“add_objX”更改的影响。如果您也想这样做,我认为您必须使用模型类“save”函数并检查那里的更改。
See: www.djangoproject.com/documentation/models/save_delete_hooks/
参见:www.djangoproject.com/documentation/models/save_delete_hooks/
Greez, Nick
Greez,尼克
#6
0
A variation based on the previous excellent suggestion of Bernhard Vallant, which also preserves any possible customization provided by the base class (if any):
一种基于Bernhard Vallant之前的优秀建议的变体,它还保留了基类提供的任何可能的定制(如果有的话):
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
#1
130
You can override the admin's get_readonly_fields
method:
您可以覆盖管理员的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
#2
7
If you want to set all fields as read only just on the change view, override the admin's get_readonly_fields:
如果您希望将所有字段设置为仅在change视图上读取,请重写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
And if you want to hide save buttons on change view:
如果你想在更改视图中隐藏保存按钮:
-
Change the view
改变了观点
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)
-
Change permissions if user is trying to edit:
如果用户正在尝试编辑,请更改权限:
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
This solution has been tested over Django 1.11
这个解决方案已经在Django 1.11上进行了测试
#3
3
FYI: in case someone else runs into the same two problems I encountered:
供参考:如果有人遇到了我遇到的两个问题:
-
You should still declare any permanently readonly_fields in the body of the class, as the readonly_fields class attribute will be accessed from validation (see django.contrib.admin.validation: validate_base(), line.213 appx)
您仍然应该在类的主体中声明任何永久性的readonly_fields,因为从验证中将访问readonly_fields类属性(参见django.后悔.admin)。验证:validate_base()。213附录)
-
This won't work with Inlines as the obj passed to get_readonly_fields() is the parent obj (I have two rather hacky and low-security solutions using css or js)
由于传递给get_readonly_fields()的obj是obj的父类(我有两个使用css或js的相当陈腐和低安全性的解决方案),所以这对inline是不起作用的。
#4
0
You can do this by overriding the formfield_for_foreignkey method of the ModelAdmin:
可以通过重写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)
#5
0
Got a similar problem. I solved it with "add_fieldsets" and "restricted_fieldsets" in the ModelAdmin.
有一个类似的问题。我在ModelAdmin中使用“add_fieldsets”和“restricted ted_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', )}),
)
Please see e.g.: http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/admin.py
请见如:http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/admin.py
But this doesn't protect your model from later changes of "add_objX". If you want this too, I think you have to go the way over the Model class "save" function and check for changes there.
但是这并不能保护您的模型不受以后“add_objX”更改的影响。如果您也想这样做,我认为您必须使用模型类“save”函数并检查那里的更改。
See: www.djangoproject.com/documentation/models/save_delete_hooks/
参见:www.djangoproject.com/documentation/models/save_delete_hooks/
Greez, Nick
Greez,尼克
#6
0
A variation based on the previous excellent suggestion of Bernhard Vallant, which also preserves any possible customization provided by the base class (if any):
一种基于Bernhard Vallant之前的优秀建议的变体,它还保留了基类提供的任何可能的定制(如果有的话):
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