Hi all,
I want to be able to add extra fields, that I control, to the admin forms.
For example, a read-only list of documents authored by the user, which is
ManyToMany, so an InlineAdmin doesn't work.
The admin module docs don't really say whether this is possible or not.
They have much more to say about excluding, reordering and making fields
read-only. However there are hints that it's possible (for ModelForm):
* "Also, if you manually add the excluded fields back to the form, they
will not be initialized from the model instance."
* "you can extend and reuse ModelForms by inheriting them. This is useful
if you need to declare extra fields"
And the admin interface uses ModelForm and allows you to specify your own
form. So I create a custom subclass of ModelForm with the new field:
from django_tables2 import tables
class DocumentsAuthoredTable(tables.Table):
...
class DocumentsAuthoredWidget(widgets.Widget):
def render(self, name, value, attrs=None):
table = DocumentsAuthoredTable(value)
return table.as_html()
class DocumentsAuthoredField(forms.Field):
widget = DocumentsAuthoredWidget
class IntranetUserReadOnlyForm(ModelForm):
class Meta:
model = models.IntranetUser
documents_authored = DocumentsAuthoredField()
Now I have to do some ugly things. The widget has no access to the
instance (model), so I have to provide some data for it, by adding a
method to either the IntranetUserReadOnlyForm or the model. I don't want
to introduce a circular dependency in the model, so I have to do this in
the form:
def __init__(self, data=None, files=None, auto_id='id_%s',
prefix=None,
initial=None, error_class=ErrorList, label_suffix=':',
empty_permitted=False, instance=None):
"""
Add a "method" to the initial data which is used to lookup the
value of documents_authored by BoundField.
"""
if initial is None:
initial = {}
from django.utils.functional import curry
initial['documents_authored'] = curry(self.get_documents_authored,
instance)
super(IntranetUserReadOnlyForm, self).__init__(data, files,
auto_id, prefix, initial, error_class, label_suffix,
empty_permitted, instance)
def get_documents_authored(self, instance):
# print "get_documents_authored(%s)" % instance
return instance.document_set.all()
And now I have to do a really horrible hack in the Admin class, to add
this field into the form:
class IntranetUserAdmin(AdminWithReadOnly):
documents_authored = None
This is because AdminReadOnlyField tries to call label_for_field() on the
field, which insists that it be a member of the Model or the Admin, not
the Form. It doesn't really care what type of attribute it is, but it
throws an exception if it's not there at all:
File "/usr/lib/pymodules/python2.6/django/template/defaulttags.py", line
227, in render
nodelist.append(node.render(context))
File "/usr/lib/pymodules/python2.6/django/template/defaulttags.py", line
190, in render
values = list(values)
File "/usr/lib/pymodules/python2.6/django/contrib/admin/helpers.py",
line 103, in __iter__
model_admin=self.model_admin)
File "/usr/lib/pymodules/python2.6/django/contrib/admin/helpers.py",
line 135, in __init__
label = label_for_field(field, form._meta.model, model_admin)
File "/usr/lib/pymodules/python2.6/django/contrib/admin/util.py", line
252, in label_for_field
raise AttributeError(message)
TemplateSyntaxError: Caught AttributeError while rendering: Unable to
lookup 'documents_authored' on IntranetUser or IntranetUserAdmin
So please can we have an easier way to add fields to an admin form?
Ideally I wouldn't have to change the Model or the Admin at all, just add
a new attribute to the custom Form.
Also please can the widget have access to the request? Rendering out a
DjangoTable (with proper links) needs this.
Cheers, Chris.
--
Aptivate | http://www.aptivate.org | Phone: +44 1223 760887
The Humanitarian Centre, Fenner's, Gresham Road, Cambridge CB1 2ES
Aptivate is a not-for-profit company registered in England and Wales
with company number 04980791.
--
You received this message because you are subscribed to the Google Groups "Django
developers" group.
To post to this group, send email to django-developers@googlegroups.com.
To unsubscribe from this group, send email to
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/django-developers?hl=en.