Rendering forms and fields

Most of the time you’ll be using morf to display, validate and process web forms.

The class HTMLForm provides shortcuts for this. Most of the time it’s convenient to create forms by subclassing this.

Basic rendering

Forms, by default, do not know anything about HTML. For that you need a morf.render.FormRenderer object. There are various flavours of FormRenderer that render in different HTML markup styles. The easiest way to get hold of a FormRenderer object is to use one of the .as_* methods on HTMLForm:

from morf import HTMLForm, fields

class MyForm(HTMLForm):

    email = fields.Str()
    name = fields.Str()

form = MyForm()
print(form.as_p())

Which outputs the rendered HTML:

<p><label for="field_email-0">Email</label><div class="control"><input id="field_email-0" name="email" required="" type="text" value="" /></div></p>...

Customizing rendering templates

You can customize the HTML generated by calling renderer():

from markupsafe import Markup
renderer = form.renderer(
    form_template='<ul class="custom-form">{{ fields|join() }}</ul>',
    row_template='<li class="custom-form-row">{{ field }}</li>',
    field_template='<span>{{ label }}: {{ control }}</span>{{ errors }}',
    errors_template=
            '<div class="oops-errors">'
            '{% for message in errors %}{{ message|e }}{% endfor %}'
            '</div>',
    label_template='<label for="{{ id }}">{{ label|e }}</label>')

print(renderer)

Which will output the HTML:

<ul class="custom-form"><li class="custom-form-row"><span><label...

The various ‘_template’ arguments are Jinja2 templates, and you can use all of the templating features of Jinja2 to customize the output. For example, if you wanted to add a Django forms style help_text attribute:

email = fields.Str(
            help_text='We will send a confirmation email to this address')

renderer = form.as_p(field_template=
        '<span>{{ label }}: {{ control }}</span>{{ errors }}'
        '{% if 'help_text' in field.options %}
        '{{ field.options.help_text|e }}'
        '{% endif %}')

For more examples, take a few minutes to look at the source code of morf.htmlform.HTMLForm and morf.render.RenderOptions.

Rendering individual fields

FormRenderer objects know which fields have already been rendered and which have not.

This lets you tailor rendering for selected fields while leaving morf to do the grunt work on the remaining fields. For example, here’s some sample form rendering code in a Jinja2 template:

<div class="column">
    {{ form.pop('username').render(class_='MyCustomCSSClass') }}
    {% for field in form.select(['email', 'password', 'password_confirm') %}
        {{ field }}
    {% endfor %}
</div>

<div class="column">
    {% for field in form %}
        {{ field }}
    {% endfor %}
</div>

This template renders the form in two separate <div> elements. The second <div> element will only contain fields not previously rendered in the first <div> element. Methods such as morf.render.FormRenderer.pop(), morf.render.FormRenderer.select(), morf.render.FormRenderer.select_to(), morf.render.FormRenderer.select_match() and morf.render.FormRenderer.select_except() give you a lot of flexibility to slice and dice the layout of fields within the form, without having to hand code everything.

class morf.htmlform.HTMLForm(raw=None, bind=None, **kwargs)

Convenience subclass of form that also implements FormRenderer

bind_input(raw, *args, **kwargs)

Bind the raw submitted value to the field

Field.extract_raw can be used to extract the raw value in the correct format for this method.

render_with

alias of morf.render.FormRenderer

renderer(**kwargs)

Return a configured FormRenderer instance

class morf.render.FieldRenderer(field, render_options, parent=None)
extract_raw(raw)

Extract the raw value for the field from the submitted input values.

This method is in the Renderer, because it is possible for a field to be rendered using a widget that splits the value into multiple inputs (eg a time represented as separate ‘hh’ and ‘mm’ inputs)

get_id()

Return a unique id, used as the basis for HTML id attributes.

The id number is incremented with each call. This is so that if the field is part of a list widget then each iteration will produce a unique id.

The id number must be a stable series. If the user wishes to script the form using javascript, having stable html ids is essential.

property is_visible

bool(x) -> bool

Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.

class morf.render.FormRenderer(*args, **kwargs)

Renderer for a Form object.

hidden()

Return a copy of the FormRenderer object limited to displaying only hidden fields.

pop(fieldname, default=[])

Return the named field, removing it from the internal list of fields to render.

select(fields, strict=False)

Return an iterator over just the named fields.

The fields will be removed from the internal of fields to render so that subsequent iteration over the FormRenderer object will not return them a second time.

select_except(fields)

Select all fields excluding those named. See select() for more information.

select_match(match)

Select all fields matching the regular expression match. The regular expression search method is used, so match will match any part of the fieldname by default, eg: select_match('address') would match both address_1 and billing_address1.

See select() for more information.

select_to(field)

Select all fields up to (but not including) the named field. See select() for more information.

visible()

Return a copy of the FormRenderer object limited to displaying only the visible fields.

class morf.render.HiddenRenderer(field, render_options, parent=None)

Renders an <input type=”hidden”> element with no other output. Used by Hidden

class morf.render.ListRenderer(field, render_options, parent=None)
extract_raw(raw)

Extract the raw value for the field from the submitted input values.

This method is in the Renderer, because it is possible for a field to be rendered using a widget that splits the value into multiple inputs (eg a time represented as separate ‘hh’ and ‘mm’ inputs)

property is_visible

bool(x) -> bool

Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.

class morf.render.NullRenderer(field, render_options, parent=None)

Produces no output when rendered. Used by Constant

class morf.render.RenderOptions(form=None, **kwargs)

Set of commonly tweaked parameters for rendering forms and fields

class morf.render.Renderer(field, render_options, parent=None)

Renders something, eg a widget, a field or an entire form.

copy()

Return a copy of the Renderer object.

All top-level attributes (including mutable structures such as processors and validators) are independently copied.

extract_raw(raw)

Extract the raw value for the field from the submitted input values.

This method is in the Renderer, because it is possible for a field to be rendered using a widget that splits the value into multiple inputs (eg a time represented as separate ‘hh’ and ‘mm’ inputs)