Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - How to add html attributes to forms on templates

Suppose I have the following template:

<div id="openid_input_area">
{{ form.openid_identifier }}
    <input name="bsignin" type="submit" value="{% trans "Sign in" %}">
</div>

How can I add a css class to form.openid_identifier?

As I am adhering to the SOC principles and I expect designers to improve the templates I do NOT want to do this on the form model but on the template itself.

I couldn't find anything on this on the docs. Is there a way to do this on the template?

like image 579
Raphael Avatar asked Feb 09 '11 23:02

Raphael


2 Answers

I've managed to code a simple solution to my problem:

I wrote a custom template tag:

from django import template

register = template.Library()

def htmlattributes(value, arg):
    attrs = value.field.widget.attrs


    data = arg.replace(' ', '')   

    kvs = data.split(',') 

    for string in kvs:
        kv = string.split(':')
        attrs[kv[0]] = kv[1]

    rendered = str(value)

    return rendered

register.filter('htmlattributes', htmlattributes)

And all I have to do at the template is:

{{ form.openid_identifier|htmlattributes:"class : something, id: openid_identifier" }}
like image 61
Raphael Avatar answered Sep 22 '22 01:09

Raphael


I don't know of any other way in plain Django. Shortcuts like form.field or form.as_p really get you started, but in the end one can fall back on plain html. That's how I see it. Not to say that there isn't any need for more control about rendering. I remember reading this discussion about form rendering on the Django mailing list.

Simon Willison is/was working on a library to give designers more control, you can find its source on github. It's a bit older, so it might not even work anymore. But regarding your question, this example looks like it could be of use to you:

{% field form.name class="myclass" %}
<!-- renders as -->
<input type="text" name="name" id="id_name" class="myclass">

Actually this functionality should be easy to achieve. You need a template tag that accepts a form field, updating the widgets attributes (those you can set on the form already) and render the field.

Iterating over a form yields instances of BoundField, that renders itself with its __unicode__ method. You would need to pass all keyword arguments to the widgets render function. A draft of this idea:

@register.simple_tag
def field(boundfield, **kwargs):
    if self.field.show_hidden_initial:
        return self.as_widget(attrs=kwargs) + self.as_hidden(only_initial=True)
    return self.as_widget(attrs=kwargs)
like image 32
Reiner Gerecke Avatar answered Sep 21 '22 01:09

Reiner Gerecke