I\'m wrestling with how to best create HTML pages in Django that can either be used for displaying or editing data. That is, I\'d like the field\'s values to appear as text in d
Have I missed something
Forms not only display the field widgets but also handle the post data. A post sent would cause it to process the data cleanup, form and field error handling, etc.
It's kind of breaking the pattern - why create and render a form object only to tweak it not to look like a form?
If you are worried about too much work on templates, try to solve it with template inheritance in a best possible way. If you are very sure you want to change only the field tag, you can make sth like
{% if form %}
{% for error in form.field.errors %}
{{ error|escape }}
{% endfor %}
{{ form.field }}
{% else %}
{{ object.field }}
{% endif %}
for every field, but IMO that's not the point, YMMV.
Also what comes to mind (thinking of your solution) is dynamically attach widgets to form fields, but that'd be overengineering.
Since you are saving the data, you must have a model attached to the form somehow, a modelform or not. So you can just use that model directly to get the values and render it in a template like you want.
The above suggestion would be possible, but since forms can be rather complex, it's probably not an easy task or worth the bother. Depends on how often you want to do this. But then it would probably be easier to create a filter for the model instead of the form.
I have the same problem. Right now I have separate templates for display and editing; the former renders object fields, the latter form fields (but sometimes also object fields, for things which are not editable). The HTML structure can be quite complex: for example, on some pages I have large tables representing a multi-level hierarchy of objects. As a result, I end up with a large amount of duplicated code in the two templates, which is the opposite of DRY.
I have used template filters with form fields before, to save code when displaying errors together with the field. I think it would be a viable solution in this case. Another possibility may be to use a ModelForm subclass which can be told to render uneditable versions of the fields. This would help keep the templates simple. You could even render both the static and the editable version of a field, and use JavaScript to switch between them, activating and deactivating an editing mode.
Answering my own question, apparently. I ended up with a three-part solution:
Step one:
form.model = Model(...)
Step two:
{{form.field1.label}} {% render form.field1 user action %} {{form.field2.label}} {% render form.field2 user action %}
Step three:
Something like:
def render(formfield, user, action, default_text="Private"): if not user.is_authenticated(): action = "view" if action == "view": if user.is_authenticated(): fieldname = formfield.name retval = str(getattr(formfield.form.model, fieldname)) else: retval = default_text else: retval = formfield.as_widget() return retval