Put this code and import it where you define your ModelAdmin-classes.
# typical admin.py file:
from django.contrib import admin
from foo.bar import ReadOnlyAdminFields
class MyModelAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
readonly = ('field1', 'field2',)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | from django import forms
class ReadOnlyWidget(forms.Widget):
def __init__(self, original_value, display_value):
self.original_value = original_value
self.display_value = display_value
super(ReadOnlyWidget, self).__init__()
def render(self, name, value, attrs=None):
if self.display_value is not None:
return unicode(self.display_value)
return unicode(self.original_value)
def value_from_datadict(self, data, files, name):
return self.original_value
class ReadOnlyAdminFields(object):
def get_form(self, request, obj=None):
form = super(ReadOnlyAdminFields, self).get_form(request, obj)
if hasattr(self, 'readonly'):
for field_name in self.readonly:
if field_name in form.base_fields:
if hasattr(obj, 'get_%s_display' % field_name):
display_value = getattr(obj, 'get_%s_display' % field_name)()
else:
display_value = None
form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name, ''), display_value)
form.base_fields[field_name].required = False
return form
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
This worked great. Should be part of the main Django branch IMHO, seems to be a bit of functionality that is needed quite often!
#
It works - but when I try to update existing data via admin interface, I get blocked and receive the errormessage:
"Enter a list of values."
This happens on a DateTime field. I have not tried others so far.
#
I think this needs to output a hidden input field on render, or else the form that this belongs to will not validate. I think just by inheriting from widget.HiddenInput and calling super on render, it should (basically) work.
#
I see, it doesn't use a hidden field because it intercepts the value_from_datadict call to the widget. Unfortunately, when the field owning the widget expects a form value isn't the same as the object property value -- as is the case for widgets that post more than 1 value, or foreign key values where the field expects an id -- the widget doesn't provide the value in the right format for the field.
#
Will there be some way to also enable this very useful fields in InlineForms as well? As snippet below, does not seems to fix it.
#
If you want activate this feature only for a specific user group, put this code and import it where you define your ModelAdmin-classes.
Limitation: the name of the group (LimitedGroup) is hard coded here, which is not recommended. But it still provides some hints on how to do it. Man can imagine a simple model class to add/configure those limited groups.
If you have some better code feel free to share! ;)
#
To make it work with ForeignKey or ManyToManyField, I changed line 27-31:
I hope it helps
#
EDIT: I forgot to tell this, change the code after those line and this is complete code of "ReadOnlyAdminFields"
#
get_form()
should accept arbitrary kwargs as well to match the signature of the function being overridden.#
I couldn't get this to work - I get the following error:
'NoneType' object is not callable
Traceback: File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py" in get_response 99. response = callback(request, callback_args, callback_kwargs) File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/options.py" in wrapper 237. return self.admin_site.admin_view(view)(args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in call 36. return self.decorator(self.func)(*args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in _wrapped_view 86. response = view_func(request, args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in call 36. return self.decorator(self.func)(args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func 70. response = view_func(request, *args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/sites.py" in inner 187. return view(request, args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/utils/decorators.py" in _wrapped_view 86. response = view_func(request, args, kwargs) File "/usr/local/lib/python2.6/dist-packages/django/db/transaction.py" in _commit_on_success 295. res = func(*args, kw) File "/usr/local/lib/python2.6/dist-packages/django/contrib/admin/options.py" in change_view 894. form = ModelForm(instance=obj)
Exception Type: TypeError at /admin/snippets/snippet/1/ Exception Value: 'NoneType' object is not callable
#
This appears to now be built in to django.contrib.admin as readonly_fields and works with StackedInline and TabularInline in addition to ModelAdmin.
https://github.com/django/django/blob/master/django/contrib/admin/options.py
#
Please login first before commenting.