Index: trunk/exodus/contrib.py
===================================================================
--- trunk/exodus/contrib.py	(revision 6425)
+++ trunk/exodus/contrib.py	(revision 6425)
@@ -0,0 +1,36 @@
+from django import forms
+
+# http://www.djangosnippets.org/snippets/937/
+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
+
