Django: How do I add arbitrary html attributes to input fields on a form?

92,094

Solution 1

Check this page

city = forms.CharField(widget=forms.TextInput(attrs={'autocomplete':'off'}))

Solution 2

Sorry for advertisment, but I've recently released an app (https://github.com/kmike/django-widget-tweaks) that makes such tasks even less painful so designers can do that without touching python code:

{% load widget_tweaks %}
...
<div class="field">
   {{ form.city|attr:"autocomplete:off"|add_class:"my_css_class" }}
</div>

or, alternatively,

{% load widget_tweaks %}
...
<div class="field">
   {% render_field form.city autocomplete="off" class+="my_css_class" %}
</div>

Solution 3

If you are using "ModelForm":

class YourModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(YourModelForm, self).__init__(*args, **kwargs)
        self.fields['city'].widget.attrs.update({
            'autocomplete': 'off'
        })

Solution 4

If you are using ModelForm, apart from the possibility of using __init__ as @Artificioo provided in his answer, there is a widgets dictionary in Meta for that matter:

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title', 'birth_date')
        widgets = {
            'name': Textarea(attrs={'cols': 80, 'rows': 20}),
        }

Relevant documentation

Solution 5

I did't want to use an entire app for this thing. Instead I found the following code here https://blog.joeymasip.com/how-to-add-attributes-to-form-widgets-in-django-templates/

# utils.py
from django.template import Library
register = Library()

@register.filter(name='add_attr')
def add_attr(field, css):
    attrs = {}
    definition = css.split(',')

    for d in definition:
        if ':' not in d:
            attrs['class'] = d
        else:
            key, val = d.split(':')
            attrs[key] = val

    return field.as_widget(attrs=attrs)

use the tag in the html file

{% load utils %}
{{ form.field_1|add_attr:"class:my_class1 my_class2" }}
{{ form.field_2|add_attr:"class:my_class1 my_class2,autocomplete:off" }}
Share:
92,094

Related videos on Youtube

User
Author by

User

Updated on July 08, 2022

Comments

  • User
    User almost 2 years

    I have an input field that is rendered with a template like so:

    <div class="field">
       {{ form.city }}
    </div>
    

    Which is rendered as:

    <div class="field">
        <input id="id_city" type="text" name="city" maxlength="100" />
    </div>
    

    Now suppose I want to add an autocomplete="off" attribute to the input element that is rendered, how would I do that? Or onclick="xyz()" or class="my-special-css-class"?

  • User
    User almost 14 years
    Ok thank you. In my case I am using ModelForm so I am not explicitly defining the form fields (e.g. class AddressForm(forms.ModelForm): class Meta: model = models.Address ) Does this mean I can't use ModelForm or is there something special I need to do?
  • User
    User almost 14 years
  • jmagnusson
    jmagnusson about 13 years
    Nice app Mike, just what I was looking for!
  • James Lin
    James Lin over 12 years
    the documentation does not tell you to add "widget_tweaks" into your installed app in settings, might be worth to put that in to the documentation.
  • Mikhail Korobov
    Mikhail Korobov over 12 years
    Hi James, it is not stressed but in the 'Installation' section there is already a note about adding 'widget_tweaks' to INSTALLED_APPS.
  • asgaines
    asgaines almost 10 years
    Hmmm, this seems to overwrite the element descending from the original model if inheriting as modelform. Anyone know how to keep from doing this? I want to keep access to the model help_text attribute
  • Stuart Axon
    Stuart Axon almost 10 years
    @InfinitelyLoopy inside the init for form, you can add some code to grab the field and modify its widgets attributes. Here is some I used earlier to modify 3 fields: ``` for field_name in ['image', 'image_small', 'image_mobile']: field = self.fields.get(field_name) field.widget.attrs['data-file'] = 'file' ```
  • Stuart Axon
    Stuart Axon almost 10 years
    Sorry for the bored formatting, I can never remember how to format code on S/O after being on github :/
  • Wilhelm Klopp
    Wilhelm Klopp over 9 years
    What about attributes that don't take arguments like 'required' and 'autofocus' ?
  • trpt4him
    trpt4him almost 9 years
    Trying to figure out why this got less upvotes than the answer above... sometimes I think Django/Python developers just prefer the harder way of doing things...
  • Akhorus
    Akhorus over 8 years
    @trpt4him Using the init approach is useful to create a Mixin or Base Class that you can re-use in other Forms. This is typicall in a medium to big-scale project. The Meta.widgets is great for a single Form. So, both are good answers.
  • Ljubisa Livac
    Ljubisa Livac over 8 years
    @MikhailKorobov thank you so much for this app, it helped me a lot! This was just the right thing i was looking for. I needed a form from ModelForm and didn't want to manually insert this attributes to every single field (40 of them), so i elegantly managed to achieve same result in seconds :) This should be the accepted answer!
  • Mikael Lindlöf
    Mikael Lindlöf about 8 years
    Good! No need to explicitly define all widgets now.
  • Anuj TBE
    Anuj TBE over 6 years
    I was planning to write such application. Thanks to saving my effort.
  • David Dahan
    David Dahan over 6 years
    This solution is bad because there is no separation of concerns. HTML attributes should not be written in python code IMO. Mikhail Korobov solution is superior.
  • David Dahan
    David Dahan over 6 years
    This should be the accepted answer, even if it's not the official solution. It's way better that writing HTML attributes in python code.
  • Katharine Osborne
    Katharine Osborne about 6 years
    This is not useful if you need to extract info from the model that isn't accessible in the template to put into say, a data attribute.
  • utkarsh2k2
    utkarsh2k2 over 5 years
    What if there I am using the same form for create and edit and I want to disable the field only in edit?
  • Gregorio
    Gregorio about 4 years
    I like this solution because we can manage HTML attributes in the V of the MVC: the template. @Katharine Osborne, you can pass to the template any info you need.
  • CutePoison
    CutePoison about 3 years
    How would you use it to set properties w/o values e.g "novalidate"?
  • run_the_race
    run_the_race about 2 years
    Just to clarify, this does not work for django.forms.Form?