Form¶
Base class: Part
Describe a Form. Example:
class MyForm(Form):
a = Field()
b = Field.email()
form = MyForm().bind(request=request)
You can also create an instance of a form with this syntax if it’s more convenient:
form = Form(
fields=dict(
a=Field(),
b=Field.email(),
),
).bind(request=request)
In the common case the fields namespace will contain only instances of Field, but
iommi actually supports arbitrary Part objects. For example:
form = Form(
fields=dict(
# Display a and b inside a box
box=html.div(
attrs__class__box=True,
children__a=Field(),
children__b=Field.email(),
),
# And c regularly
c=Field(),
)
)
So that writing the application logic (e.g. validation and post handlers) is independent
of minor changes to the layout, after bind the fields namespace of the form will contain
only instances of Field keyed by their _name independently of how deep they are in the
hierarchy. Given the above, an appropriate post_handler would be:
def post_handler(form, **_):
if not form.is_valid():
return
print(form.fields.a.value, form.fields.b.value, form.fields.c.value)
# And not:
# print(form.fields.box.a.value, form.fields.box.b.value, form.fields.c.value)
Use of Form.layout:
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy
from iommi._web_compat import Template
class UserForm(Form):
class Meta:
auto__model = get_user_model()
layout = Panel(dict(
p_main=Panel.fieldset(dict(
username=Panel.field(),
p_fullname=Panel.row(dict(
first_name=Panel.field(col__attrs__class__firstname=True),
last_name=Panel.field(),
)),
# examples of custom html parts:
p_foo=Panel.row(dict(
p_bar=gettext_lazy('Some plain text'),
p_baz=Template('{% load i18n %}<span>{% translate "Foobar!" %}</span>'),
)),
p_qux=Fragment(template='path/to/template.html'),
p_quux=html.h3('Quux'),
p_corge__template='path/to/another_template.html',
)),
p_permissions=Panel.fieldset(dict(
# ...
)),
p_error=Panel.alert('Error!', level='error'),
))
Refinable members¶
action_class¶
Type: Type[Action]
actions¶
Type: Namespace
actions_template (evaluated)¶
Type: Union[str, Template]
Default: iommi/form/actions.html
after (evaluated)¶
Type: Union[int, str]
See after
assets¶
Type: Namespace
See assets
attr (evaluated)¶
Type: str
See attr
attrs (evaluated)¶
Type: Attrs
See attributes
auto¶
Type: FormAutoConfig
See auto
editable¶
Type: bool
Default: True
- Cookbook:
endpoints¶
Type: Namespace
See endpoints
errors¶
Type: Errors
- Cookbook:
extra¶
Type: Dict[str, Any]
See extra
extra_evaluated¶
Type: Dict[str, Any]
See extra
extra_params¶
See extra_params
field_group¶
Type: Namespace
fields¶
Type: Namespace
fields_template (evaluated)¶
Type: Union[str, Template]
- Cookbook:
h_tag (evaluated)¶
Type: Union[Fragment, str]
See title
include (evaluated)¶
Type: bool
See include
instance¶
Type: Any
iommi_style¶
Type: str
See iommi_style
layout (evaluated)¶
Type: Optional[Panel]
layout_render_unused_fields (evaluated)¶
Type: bool
Default: False
layout_template (evaluated)¶
Type: Union[NoneType, str, Template]
Default: lambda form, **_: 'iommi/form/layout.html' if form.layout is not None else None
member_class¶
Type: Type[Field]
model (evaluated)¶
Type: Type[Model]
page_class¶
Type: Type[Page]
post_validation¶
read_nested_form_from_instance¶
Read the nested forms instance from the parent forms instance.
This is analogous to Field.read_from_instance but for nested forms.
template (evaluated)¶
Type: Union[str, Template]
- Default:
iommi/form/form.html See template
title (evaluated)¶
Type: Fragment
See title
write_nested_form_to_instance¶
Write the nested_form to the instance.
This is analogous to Field.write_to_instance but for nested forms.
Shortcuts¶
Form.create¶
Parent: Form.crud
Defaults¶
actions__submit__post_handleriommi.form.create_object__post_handler
extra__is_createTrue
Form.create_or_edit¶
Parent: Form.crud
Defaults¶
actions__submit__post_handleriommi.form.create_or_edit_object__post_handler
extra__is_createNone
- Cookbook:
Form.crud¶
Defaults¶
extra__pre_save_all_but_related_fieldslambda **kwargs: None, # pragma: no mutate
extra__on_save_all_but_related_fieldslambda **kwargs: None, # pragma: no mutate
extra__pre_savelambda **kwargs: None, # pragma: no mutate
extra__on_savelambda **kwargs: None, # pragma: no mutate
extra__on_deletelambda **kwargs: None, # pragma: no mutate
extra__redirectlambda redirect_to, **_: HttpResponseRedirect(redirect_to)
extra__redirect_toNone
extra__crud_typelambda form, **_: 'create' if form.instance is None else 'edit'
extra__new_instancelambda form, **_: form.model()
autoNamespace()
Form.delete¶
Parent: Form.crud
Defaults¶
actions__submit__call_target__attributedelete
actions__submit__post_handleriommi.form.delete_object__post_handler
extra__crud_typedelete
editableFalse
fields__iommi_default_text{'call_target': <class 'iommi.fragment.Fragment'>, 'include': <function Form.<lambda> at 0x7eb20c68c180>, 'after': 0, 'tag': 'p', 'children__text': <function Form.<lambda> at 0x7eb20c68c720>}
Form.edit¶
Parent: Form.crud
Defaults¶
actions__submit__post_handleriommi.form.edit_object__post_handler
extra__is_createFalse
Methods¶
add_error¶
Explicitly add an error message to the form’s global error set.
Example:
def post_validation(form, **_):
form.add_error('global error')
form = Form.create(
auto__model=Album,
post_validation=post_validation,
)
apply¶
Write the new values specified in the form into the instance specified.
as_view¶
get_errors¶
Get a dict containing two keys:
globalfor errors global to the entire form.fieldsfor errors specific to fields. This is itself a dict with a key for each field.
get_field¶
get_nested_form¶
is_target¶
is_valid¶
Is the form valid? Can be called inside forms post_validation hook to determine if the individual fields were all valid.