Django forms
form.as_ul
form.as_p
form.as_table
•
•
•
Slide 4
Slide 4 text
Django forms
class ExampleForm(forms.Form):
username = forms.CharField()
email = forms.CharField()
Slide 5
Slide 5 text
Django forms
{{ example_form.as_ul }}
Username:
Email:
Slide 6
Slide 6 text
How about divs?
Slide 7
Slide 7 text
Reorder fields?
Slide 8
Slide 8 text
Django forms
Moving chunks of code
class ExampleForm(forms.Form):
email = forms.CharField()
username = forms.CharField()
•
Slide 9
Slide 9 text
class ExampleForm(forms.Form):
email = forms.CharField()
username = forms.CharField()
class ExampleForm(forms.Form):
username = forms.CharField()
email = forms.CharField()
Django forms
Moving chunks of code
•
Slide 10
Slide 10 text
Django forms
Make comment the first field?
class ExampleForm(forms.Form):
email = forms.CharField()
username = forms.CharField()
class ExtraFieldForm(ExampleForm):
comment = forms.CharField()
•
Slide 11
Slide 11 text
Django forms
self.fields is a SortedDict
self.fields.keyOrder is a list ['username', 'email', 'comment']
class ExtraFieldForm(ExampleForm):
comment = forms.CharField()
def __init__(self, *args, **kwargs):
super(ExtraFieldForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = ['comment', 'email', 'username']
•
•
Slide 12
Slide 12 text
Django forms
What if I have 100 fields?
class ExtraFieldForm(ExampleForm):
comment = forms.CharField()
def __init__(self, *args, **kwargs):
super(ExtraFieldForm, self).__init__(*args, **kwargs)
self.fields.keyOrder.remove('comment')
self.fields.keyOrder.insert(0, 'comment')
Slide 13
Slide 13 text
Django ModelForms
ModelForms are different, why?
class ExampleForm(forms.ModelForm):
class Meta:
model = ExampleModel
fields = ('username', 'email')
•
Slide 14
Slide 14 text
Customize output?
Slide 15
Slide 15 text
Asteriks for required fields
{% for field in form %}
{{ field }} {% if field.field.required %}(*){% endif %}
{% endfor %}
Slide 16
Slide 16 text
Asteriks for required fields
{% for field in form %}
{{ field }} {% if field.field.required %}(*){% endif %}
{% endfor %}
What about field.errors ?
What about form.non_field_errors ?
etc.
•
•
•
Slide 17
Slide 17 text
Something more
complex?
Slide 18
Slide 18 text
No content
Slide 19
Slide 19 text
django-crispy-forms
Formerly known as django-uni-form, created by Daniel Greenfeld
@pydanny in 2008
I joined the project in the middle of 2010 and became lead developer
38 contributors
Tested and thoroughly used
Two template packs: bootstrap & uni_form CRISPY_TEMPLATE_PACK
•
•
•
•
•
Slide 20
Slide 20 text
django-crispy-forms
A filter |crispy
A tag {% crispy %}
They work on forms, modelforms and formsets
•
•
•
Slide 21
Slide 21 text
|crispy filter
Easy div format
No need to change form code at all
{% load crispy_forms_tags %}
{{ example_form|crispy }}
•
•
Slide 22
Slide 22 text
Django forms
{{ example_form|crispy }}
Username*
Email*
[...]
Slide 23
Slide 23 text
No content
Slide 24
Slide 24 text
{% crispy %} tag
I don't like writing HTML for forms
I need customization power
They need to be as DRY as possible
•
•
•
Slide 25
Slide 25 text
{% crispy %} tag
{% crispy form [helper] %}
{% crispy example_form %}
Username*
[...]
Slide 26
Slide 26 text
{% crispy %} tag
{% crispy form [helper] %}
{% crispy example_form %}
Username*
[...]
How do we customize this output?
Slide 27
Slide 27 text
FormHelper
They control global form rendering behaviour
They are form decoupled
•
•
Special attribute layout and Layout class
forms.py
Template
class ExtraFieldForm(forms.Form):
helper = FormHelper()
helper.layout = Layout('comment', 'username', 'email')
{% crispy example_form %}
Slide 35
Slide 35 text
Layout(
'comment',
'email',
'username',
)
Layouts
Basic Layout for ExtraFieldForm
Slide 36
Slide 36 text
Layouts
Custom output is defined by a Python layout
Flexible and highly reusable
•
•
Slide 37
Slide 37 text
Layouts
A bit more complex Layout
Layout(
Div(
'comment',
'username',
css_id="div-wrapping-comment-and-username"
),
)
Slide 38
Slide 38 text
Layouts
A bit more complex Layout
Layout(
Div(
'comment',
'username',
css_id="div-wrapping-comment-and-username"
),
)
Beware that layouts are rendered strict
Slide 39
Slide 39 text
Layouts
Layout power comes from layout objects:
They are Python classes
Every layout object has an associated template
•
•
Dynamic Layouts
! If you manipulate a helper, use an instance variable
class ExampleForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.layout = Layout(
'comment',
'username'
)
All selects using chosen
field.html
{% if field|css_class == "select" %}
{% crispy_field field 'class' 'chzn-select' %}
{% endif %}
{% if field|css_class != "checkboxselectmultiple" and
field|css_class != "radioselect" and
field|css_class != "select" %}
[...]
Slide 67
Slide 67 text
Field labels as holders
.holder {
color: #999;
font-size: 19px;
position: relative;
left: -210px;
top: 4px;
}
Slide 68
Slide 68 text
Field labels as holders
field.html (Using a custom attribute)
{% if not label_as_holder and field.label and not field|is_checkbox %}
{{ field.label|safe }}
{% endif %}
{% crispy_field field %}
{% if label_as_holder %}
{{ field.label }}
{% endif %}
Slide 69
Slide 69 text
Scratching the surface
There is more power, filters, layout objects, attributes, etc.
Javascript validation
Visit the docs django-crispy-forms.rtfd.org
There is more coming
•
•
•
•