So, you have a project already using django.forms
, and you're considering a switch to floppyforms? Here's what you need to know, assuming the only change you've made to your code is a simple change, from:
from django import forms
to:
import floppyforms as forms
Note
django.forms.*
modules
Other modules contained by django.forms
, such as forms
, utils
and formsets
have not been aliased.
Floppyforms adds a couple of HTML 5 features on top of the standard Django widgets: HTML syntax, more native widget types, the required
attribute and client-side validation.
Floppyforms uses an HTML syntax instead of Django's XHTML syntax. You will see <input type="text" ... >
and not <input type="text" />
.
Floppyforms tries to use the native HTML5 widgets whenever it's possible. Thus some widgets which used to be simple TextInputs
in django.forms
are now specific input that will render as <input type="...">
with the HTML5 types such as url
, email
. See widgets
for a detailed list of specific widgets.
For instance, if you have declared a form using django.forms:
class ThisForm(forms.Form):
date = forms.DateField()
The date
field will be rendered as an <input type="text">
. However, by just changing the forms library to floppyforms, the input will be an <input type="date">
.
In addition to the various input types, every required field has the required
attribute set to True
on its widget. That means that every <input>
widget for a required field will be rendered as <input type="..." ... required>
. This is used for client-side validation: for instance, Firefox 4 won't let the user submit the form unless he's filled the input. This saves HTTP requests but doesn't mean you can stop validating user input.
Like with the required
attribute, the pattern
attribute is especially interesting for slightly more complex client-side validation. The SlugField
and the IPAddressField
both have a pattern attached to the <input>
.
However having these validations backed directly into the HTML and therefore allowing the browser to validate the user input might not always what you want to have. Sometimes you just want to have a form where it should be allowed to submit invalid data. In that case you can use the novalidate
attribute on the <form>
HTML tag or the formnovalidate
attribute on the submit button:
<form action="" novalidate>
This input will not be validated:
<input type="text" required />
</form>
<form action="">
Another way to not validate the form in the browser is using the
formnovalidate attribute on the submit button:
<input type="submit" value="cancel" formnovalidate>
</form>
Read the corresponding documentation for novalidate and formnovalidate on the Mozilla Developer Network if you want to know more.
Prior to version 1.2 of django-floppyforms, you had to take some manual efforts to make your modelforms work with floppyforms. This is now done seemlesly, but since this was introduced a backwards incompatible change, it was necessary to provde a deprecation path.
So if you start out new with django-floppyforms just use import floppyforms.__future__ as forms
as your import instead of import floppyforms as forms
when you want to define modelforms.
For more information see the section about modelforms in the usage
documentation <usage-modelforms>
.
If you use HTML in the help_text
value for a Django form field and are not using django-floppyforms, then you will get the correct HTML rendered in the template. For example you have this form:
from django import forms
class DjangoForm(forms.Form):
myfield = forms.CharField(help_text='A <strong>help</strong> text.')
When you now use this form with {{ form.as_p }}
in the template, you will get the help text put in the template as it is, with no HTML escaping. That might imply a security risk if your help text contains content from untrusted sources. django-floppyforms applies autoescaping by default to the help text. So if you define:
import floppyforms as forms
class FloppyForm(forms.Form):
myfield = forms.CharField(help_text='A <strong>help</strong> text.')
And then use {{ form.as_p }}
, you will get an output that contains A <strong&;gt;help</strong> text.
. You can disable the autoescaping of the help text by using Django's mark_safe
helper:
from django.utils.html import mark_safe
import floppyforms as forms
class FloppyForm(forms.Form):
myfield = forms.CharField(help_text=mark_safe('A <strong>help</strong> text.'))
The use of a non-empty TEMPLATE_STRING_IF_INVALID
setting can impact rendering. Missing template variables are rendered using the content of TEMPLATE_STRING_IF_INVALID
but filters used on non-existing variables are not applied (see django's documentation on how invalid template variables are handled for more details).
django-floppyforms assumes in its predefined form layouts that all filters are applied. You can work around this by making your TEMPLATE_STRING_IF_INVALID
evaluate to False
but still keep its string representation. Here is an example how you could achieve this in your settings.py
:
# on Python 2
class InvalidVariable(unicode):
def __nonzero__(self):
return False
# on Python 3
class InvalidVariable(str):
def __bool__(self):
return False
TEMPLATE_STRING_IF_INVALID = InvalidVariable(u'INVALID')
If you need to get the same output as standard Django forms:
- Override
floppyforms/input.html
,floppyforms/radio.html
,floppyforms/clearable_input.html
,floppyforms/textarea.html
andfloppyforms/checkbox_select.html
to use an XHTML syntax - Remove the
required
attribute from the same templates, as well asfloppyforms/select.html
Make sure your fields which have HTML5 widgets by default get simple
TextInputs
instead:class Foo(forms.Form): url = forms.URLField(widget=forms.TextInput)