Advanced¶
Composers
allows declarative configuration with the help of class attributes which
should be enough for many simple cases.
Just inherit from your composer from base composer class and set attributes and options you want to override.
from siteforms.composers.bootstrap5 import Bootstrap5
class Composer(Bootstrap5):
opt_render_labels = False
opt_placeholder_label = True
attrs_help = {'class': 'some', 'data-one': 'other'}
Attributes¶
attrs
- Attributes to apply to basic elements (form, fields, widget types, groups).attrs_labels
- Attributes to apply to labels.attrs_help
- Attributes to apply to hints.attrs_feedback
- Attributes to apply to feedback (validation notes).wrappers
- Wrappers for fields, groups, rows, submit button.groups
- Map alias to group titles. Groups can be addressed inlayout
.layout
- Layout instructions for fields and form.
Options¶
opt_form_inline
- Make form inline.opt_render_form_tag
- Render form tag. On by default.opt_label_colon
- Whether to render colons after label’s texts.opt_render_labels
- Render label elements.opt_render_help
- Render hints (help texts).opt_placeholder_label
- Put title (verbose name) into field’s placeholders.opt_placeholder_help
- Put hint (help text) into field’s placeholders.opt_title_label
- Put title (verbose name) into field’s title.opt_title_help
- Put hint (help text) into field’s title.opt_tag_help
- Tag to be used for hints.opt_tag_feedback
- Tag to be used for feedback.opt_submit
- Submit button text. If not set, submit button won’t be added into this form.opt_submit_name
- Submit button name.
Macroses¶
Macroses are a quick way to address various objects.
They can be used as keys in Attributes
(see above).
ALL_FIELDS
- Denotes every field.ALL_GROUPS
- Denotes every group.ALL_ROWS
- Denotes every row.FORM
- Denotes a form.SUBMIT
- Submit button.
ALL_FIELDS in Layout¶
ALL_FIELDS
macros can be used in many places in layout.
It expands into rows for each field which has not been addressed so far.
As group value¶
layout = {
FORM: {
'basic': [ # group
['title', 'date_created'], # row1
'contents', # row2
],
'other': ALL_FIELDS, # rest rows
}
}
As group row¶
layout = {
FORM: {
'basic': [ # group
['title', 'date_created'], # row1
ALL_FIELDS, # rest rows
],
}
}
Subforms¶
Sometimes you may want to represent an entire other form as a field of you main form.
This can be considered as an alternative to complex widgets.
from siteforms.composers.bootstrap5 import Bootstrap5
from siteforms.toolbox import ModelForm, Form
class SubForm(Form):
"""This form we'll include in our main form."""
class Composer(Bootstrap5):
opt_render_labels = False
opt_placeholder_label = True
field1 = fields.CharField(label='field1')
field2 = fields.ChoiceField(label='field1')
def get_subform_value(self):
"""You may override this method to apply value casting.
Be default it returns subform's cleaned data dictionary
(convenient for JSONField in main form).
The result of this method would became the value of main form field.
"""
value = super().get_subform_value()
return f"{value['field1']} ----> {value['field2']}"
class MyForm(ModelForm):
"""That would be our main form.
Let's suppose it has `myfield` field, which value
we want to represent in a subform.
"""
subforms = {'myfield': SubForm} # Map field name to subform class.
class Composer(Bootstrap5):
opt_columns = True
class Meta:
model = MyModel
fields = '__all__'
After MyForm instance is validated (.is_valid()
), subform fields values
are gathered (see .get_subform_value()
) and placed into main form cleaned_data
.
Multiple forms¶
You may put more than one form from the same view.
For that to wok properly please use prefix
for your forms.
form1 = MyForm1()
form2 = MyForm2(prefix='form2')
form3 = MyForm3(prefix='form3')
Prefix attribute may also be declared in form class.