Django foreign keys only
I have two models, one is Employee and the other is Asset, with a Many-to-One relationship between Asset and Employee. And the Asset is added as a StackedInline field to the Employee admin interface, I can still make the Asset as a read-only field in Employee Admin.
My intention was to show all the assets that the employee currently holds in Admin so that he doesn't accidentally delete it.
source to share
Edit: Actually, I don't think this will work for inline models.
Django will be adding its own read-only fields in Django 1.1, due out around mid-March.
read-only fields ( http://www.djangosnippets.org/snippets/937/ )
This snippet will allow you to set fields as read-only in admin.
source to share
use this code and import it into admin.py as ReadonlyAdmin.This is a modified form of readonly admin.
from django import forms
from django.utils.safestring import mark_safe
from datetime import datetime
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
#to make fields foreignkey readonly
class ReadOnlyAdminFields(object):
def get_form(self, request, obj=None):
form = super(ReadOnlyAdminFields, self).get_form(request, obj)
if hasattr(self, 'readonly') and obj is not None:
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
if getattr(obj, field_name).__class__ in [unicode , long, int, float, datetime, list]:
form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name), display_value)
else:
form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name).id, display_value)
form.base_fields[field_name].required = False
return form
source to share
If you only want to display employee assets, you can change the default django admin change_form.html. (and you can also disable inline first)
To override the default admin templates, copy the admin template folder to your local django templates folder ($ {TEMPLATE_DIRS} in your settings.py file)
And there is this block in the change_form.html file,
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
Used to display inline strings, and here you can do some additional information like a list of assets of the current employee and place them above where the inline strings originate from.
And now the question is, how do I provide this additional information to this template? This can be done by overriding the change_view () function in your Employee admin model.
For example in your admin.py
class EmployeeAdmin(admin.ModelAdmin):
...
def change_view(self, request, object_id, extra_context=None):
assets = Asset.objects.filter(employee=Employee.objects.get(id=object_id))
context_data = {'inlines': assets, }
return super(EmployeeAdmin, self).change_view(request, object_id, extra_context=context_data)
Now go back to your admin change_form.html, user template tags to display the extra_context from your EmployeeAdmin.
eg,
{% for inline in inlines %}
{{ inline }}
{% endfor %}
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
Hope it helps and this is as of django 1.2.4
source to share