Widgets have a template_name attribute that point to the template to use when rendering the form. Default templates are provided, for instance the default template for a TextInput and other input-type widgets is floppyforms/input.html. You can easily override this template in your project-level TEMPLATE_DIRS, assuming they take precedence over app-level templates.
If you want to override the rendering behaviour only for a few widgets, you can extend a Widget class from FloppyForms and override the template_name attribute:
import floppyforms as forms
class OtherEmailInput(forms.EmailInput):
template_name = 'path/to/other_email.html'
Then, the output can be customized in other_email.html:
<input type="email"
name="{{ name }}"
id="{{ attrs.id }}"
placeholder="john@example.com"
{% if value %}value="{{ value }}"{% endif %}>
Here we have a hardcoded placeholder without needing to instantiate the widget with an attrs dictionary:
class EmailForm(forms.Form):
email = forms.EmailField(widget=OtherEmailInput())
You can also customize the template_name without subclassing, by passing it as an argument when instantiating the widget:
class EmailForm(forms.Form):
email = forms.EmailField(
widget=forms.EmailInput(template_name='path/to/other_email.html'))
For advanced use, you can even customize the template used per-render, by passing a template_name argument to the widget’s render() method.
There is also a way to add extra context. This is done by subclassing the widget class and extending the get_context() method:
class OtherEmailInput(forms.EmailInput):
template_name = 'path/to/other.html'
def get_context(self, name, value, attrs):
ctx = super(OtherEmailInput, self).get_context(name, value, attrs)
ctx['foo'] = 'bar'
return ctx
And then the other.html template can make use of the {{ foo }} context variable.
get_context() takes name, value and attrs as arguments, except for all Select widgets which take an additional choices argument.
In case you don’t need the arguments passed to get_context(), you can extend get_context_data() which doesn’t take any arguments:
class EmailInput(forms.EmailInput):
def get_context_data(self):
ctx = super(EmailInput, self).get_context_data()
ctx.update({
'placeholder': 'hello@example.com',
})
return ctx
All widget attibutes except for type, name, value and required are put in the attrs context variable, which you can extend in get_context():
def get_context(self, name, value, attrs):
ctx = super(MyWidget, self).get_context(name, value, attrs)
ctx['attrs']['class'] = 'mywidget'
return ctx
This will render the widget with an additional class="mywidget" attribute.
If you want only the attribute’s key to be rendered, set it to True:
def get_context(self, name, value, attrs):
ctx = super(MyWidget, self).get_context(name, value, attrs)
ctx['attrs']['awesome'] = True
return ctx
This will simply add awesome as a key-only attribute.