Reputation: 100462
I have a django model that I'm displaying as a form using a ModelForm. The defaults work very well for me for the most part.
However, I would like my html <input ...>
tags to have one additional attribute, namely I would like to include a placeholder
attribute, like the following:
<input placeholder="{{field.label}}" ... />
What is the easiest way to add this attribute to my html? As far as I can tell it appears I need to implement my own filter to output the field, but this seems like overkill when all i want to do is leave everything alone but add one additional attribute.
Upvotes: 23
Views: 17310
Reputation: 1198
Here is a reusable mixin for Form classes based on @Mark's method
from django.core.exceptions import ImproperlyConfigured
class PlaceholderMixin():
def placeholder_setup(self):
if not hasattr(self.Meta, 'placeholders'):
raise ImproperlyConfigured('Meta class must have a placeholders dict')
for field, placeholder in self.Meta.placeholders.items():
self.fields[field].widget.attrs['placeholder'] = placeholder
To use it, add it to a Form class and define placeholders in the Meta class:
class MyForm(forms.ModelForm, PlaceholderMixin):
class Meta:
model = MyModel
fields = [ 'name', 'description', 'choices' ]
placeholders = {
'name': 'your name',
'description': 'describe yourself'
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.placeholder_setup()
Upvotes: 0
Reputation: 48730
See the documentation
class AuthorForm(ModelForm):
class Meta:
model = Author
widgets = {
'name': TextInput(attrs={'placeholder': 'name'}),
}
You could always create your own widget that derives from TextInput and includes the placeholder attribute, and use the widgets dictionary to simply map fields to your new widget without specifying the placeholder attribute for every field.
Upvotes: 34
Reputation: 19997
Personally I prefer to use this method:
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['email'].widget.attrs['placeholder'] = self.fields['email'].label or '[email protected]'
It required more code if you don't have __init__
yet, but you don't need to specify the widget.
Upvotes: 20