wuttaweb.forms.base

Base form classes

class wuttaweb.forms.base.Form(request, fields=None, schema=None, model_class=None, model_instance=None, nodes={}, widgets={}, validators={}, defaults={}, readonly=False, readonly_fields=[], required_fields={}, labels={}, action_url=None, cancel_url=None, cancel_url_fallback=None, vue_tagname='wutta-form', align_buttons_right=False, auto_disable_submit=True, button_label_submit='Save', button_icon_submit='save', button_type_submit='is-primary', show_button_reset=False, show_button_cancel=True, button_label_cancel='Cancel', auto_disable_cancel=True)[source]

Base class for all forms.

Parameters:
  • request – Reference to current request object.

  • fields – List of field names for the form. This is optional; if not specified an attempt will be made to deduce the list automatically. See also fields.

  • schema – Colander-based schema object for the form. This is optional; if not specified an attempt will be made to construct one automatically. See also get_schema().

  • labels – Optional dict of default field labels.

Note

Some parameters are not explicitly described above. However their corresponding attributes are described below.

Form instances contain the following attributes:

request

Reference to current request object.

fields

FieldList instance containing string field names for the form. By default, fields will appear in the same order as they are in this list.

See also set_fields().

schema

colander.Schema object for the form. This is optional; if not specified an attempt will be made to construct one automatically.

See also get_schema().

model_class

Model class for the form, if applicable. When set, this is usually a SQLAlchemy mapped class. This (or model_instance) may be used instead of specifying the schema.

model_instance

Optional instance from which initial form data should be obtained. In simple cases this might be a dict, or maybe an instance of model_class.

Note that this also may be used instead of specifying the schema, if the instance belongs to a class which is SQLAlchemy-mapped. (In that case model_class can be determined automatically.)

nodes

Dict of node overrides, used to construct the form in get_schema().

See also set_node().

widgets

Dict of widget overrides, used to construct the form in get_schema().

See also set_widget().

validators

Dict of node validators, used to construct the form in get_schema().

See also set_validator().

defaults

Dict of default field values, used to construct the form in get_schema().

See also set_default().

readonly

Boolean indicating the form does not allow submit. In practice this means there will not even be a <form> tag involved.

Default for this is False in which case the <form> tag will exist and submit is allowed.

readonly_fields

A set of field names which should be readonly. Each will still be rendered but with static value text and no widget.

This is only applicable if readonly is False.

See also set_readonly() and is_readonly().

required_fields

A dict of “required” field flags. Keys are field names, and values are boolean flags indicating whether the field is required.

Depending on schema, some fields may be “(not) required” by default. However required_fields keeps track of any “overrides” per field.

See also set_required() and is_required().

action_url

String URL to which the form should be submitted, if applicable.

cancel_url

String URL to which the Cancel button should “always” redirect, if applicable.

Code should not access this directly, but instead call get_cancel_url().

cancel_url_fallback

String URL to which the Cancel button should redirect, if referrer cannot be determined from request.

Code should not access this directly, but instead call get_cancel_url().

vue_tagname

String name for Vue component tag. By default this is 'wutta-form'. See also render_vue_tag().

See also vue_component.

align_buttons_right

Flag indicating whether the buttons (submit, cancel etc.) should be aligned to the right of the area below the form. If not set, the buttons are left-aligned.

auto_disable_submit

Flag indicating whether the submit button should be auto-disabled, whenever the form is submitted.

button_label_submit

String label for the form submit button. Default is "Save".

button_icon_submit

String icon name for the form submit button. Default is 'save'.

button_type_submit

Buefy type for the submit button. Default is 'is-primary', so for example:

<b-button type="is-primary"
          native-type="submit">
  Save
</b-button>

See also the Buefy docs.

show_button_reset

Flag indicating whether a Reset button should be shown. Default is False.

show_button_cancel

Flag indicating whether a Cancel button should be shown. Default is True.

button_label_cancel

String label for the form cancel button. Default is "Cancel".

auto_disable_cancel

Flag indicating whether the cancel button should be auto-disabled, whenever the button is clicked. Default is True.

validated

If the validate() method was called, and it succeeded, this will be set to the validated data dict.

Note that in all other cases, this attribute may not exist.

append(*keys)[source]

Add some fields(s) to the form.

This is a convenience to allow adding multiple fields at once:

form.append('first_field',
            'second_field',
            'third_field')

It will add each field to fields.

get_cancel_url()[source]

Returns the URL for the Cancel button.

If cancel_url is set, its value is returned.

Or, if the referrer can be deduced from the request, that is returned.

Or, if cancel_url_fallback is set, that value is returned.

As a last resort the “default” URL from get_referrer() is returned.

get_deform()[source]

Return the deform.Form instance for the form, generating it automatically if necessary.

get_field_errors(field)[source]

Return a list of error messages for the given field.

Not useful unless a call to validate() failed.

get_fields()[source]

Returns the official list of field names for the form, or None.

If fields is set and non-empty, it is returned.

Or, if schema is set, the field list is derived from that.

Or, if model_class is set, the field list is derived from that, via get_model_fields().

Otherwise None is returned.

get_global_errors()[source]

Returns a list of “global” (not field-level) error messages for the form.

See also has_global_errors().

Returns:

List of error messages (possibly empty).

get_label(key)[source]

Get the label for given field name.

Note that this will always return a string, auto-generating the label if needed.

See also set_label().

get_model_fields(model_class=None)[source]

This method is a shortcut which calls get_model_fields().

Parameters:

model_class – Optional model class for which to return fields. If not set, the form’s model_class is assumed.

get_schema()[source]

Return the colander.Schema object for the form, generating it automatically if necessary.

Note that if schema is already set, that will be returned as-is.

get_vue_model_data()[source]

Returns a dict with form model data. Values may be nested depending on the types of fields contained in the form.

This collects the cstruct values for all fields which are present both in fields as well as the Deform schema.

It also converts each as needed, to ensure it is JSON-serializable.

Returns:

Dict of field/value items.

has_global_errors()[source]

Convenience function to check if the form has any “global” (not field-level) errors.

See also get_global_errors().

Returns:

True if global errors present, else False.

is_readonly(key)[source]

Returns boolean indicating if the given field is marked as readonly.

See also set_readonly().

Parameters:

key – Field key/name as string.

is_required(key)[source]

Returns boolean indicating if the given field is marked as required.

See also set_required().

Parameters:

key – Field key/name as string.

Returns:

Value for the flag from required_fields if present; otherwise None.

make_widget(widget_type, **kwargs)[source]

Make and return a new field widget of the given type.

This has built-in support for the following types (although subclass can override as needed):

See also set_widget() which may call this method automatically.

Parameters:
  • widget_type – Which of the above (or custom) widget type to create.

  • **kwargs – Remaining kwargs are passed as-is to the widget factory.

Returns:

New widget instance, or None if e.g. it could not determine how to create the widget.

remove(*keys)[source]

Remove some fields(s) from the form.

This is a convenience to allow removal of multiple fields at once:

form.remove('first_field',
            'second_field',
            'third_field')

It will remove each field from fields.

render_vue_field(fieldname, readonly=None, **kwargs)[source]

Render the given field completely, i.e. <b-field> wrapper with label and containing a widget.

Actual output will depend on the field attributes etc. Typical output might look like:

<b-field label="Foo"
         horizontal
         type="is-danger"
         message="something went wrong!">
   <!-- widget element(s) -->
</b-field>

Warning

Any **kwargs received from caller are ignored by this method. For now they are allowed, for sake of backwawrd compatibility. This may change in the future.

render_vue_finalize()[source]

Render the Vue “finalize” script for the form.

By default this simply returns:

<script>
  WuttaForm.data = function() { return WuttaFormData }
  Vue.component('wutta-form', WuttaForm)
</script>

The actual output may depend on various form attributes, in particular vue_tagname.

render_vue_tag(**kwargs)[source]

Render the Vue component tag for the form.

By default this simply returns:

<wutta-form></wutta-form>

The actual output will depend on various form attributes, in particular vue_tagname.

render_vue_template(template='/forms/vue_template.mako', **context)[source]

Render the Vue template block for the form.

This returns something like:

<script type="text/x-template" id="wutta-form-template">
  <form>
    <!-- fields etc. -->
  </form>
</script>

<script>
    WuttaFormData = {}
    WuttaForm = {
        template: 'wutta-form-template',
    }
</script>

Actual output will of course depend on form attributes, i.e. vue_tagname and fields list etc.

Parameters:

template – Path to Mako template which is used to render the output.

set_default(key, value)[source]

Set/override the default value for a field.

Parameters:
  • key – Name of field.

  • validator – Default value for the field.

Default value overrides are tracked via defaults.

set_default_widgets()[source]

Set default field widgets, where applicable.

This will add new entries to widgets for columns whose data type implies a default widget should be used. This is generally only possible if model_class is set to a valid SQLAlchemy mapped class.

As of writing this only looks for sqlalchemy.types.DateTime fields and if any are found, they are configured to use WuttaDateTimeWidget().

set_fields(fields)[source]

Explicitly set the list of form fields.

This will overwrite fields with a new FieldList instance.

Parameters:

fields – List of string field names.

set_grid(key, grid)[source]

Establish a grid to be displayed for a field. This uses a GridWidget to wrap the rendered grid.

Parameters:
  • key – Name of field.

  • widgetGrid instance, pre-configured and (usually) with data.

set_label(key, label)[source]

Set the label for given field name.

See also get_label().

set_node(key, nodeinfo, **kwargs)[source]

Set/override the node for a field.

Parameters:
  • key – Name of field.

  • nodeinfo – Should be either a colander.SchemaNode instance, or else a colander:colander.SchemaType instance.

If nodeinfo is a proper node instance, it will be used as-is. Otherwise an ObjectNode instance will be constructed using nodeinfo as the type (typ).

Node overrides are tracked via nodes.

set_readonly(key, readonly=True)[source]

Enable or disable the “readonly” flag for a given field.

When a field is marked readonly, it will be shown in the form but there will be no editable widget. The field is skipped over (not saved) when form is submitted.

See also is_readonly(); this is tracked via readonly_fields.

Parameters:
  • key – String key (fieldname) for the field.

  • readonly – New readonly flag for the field.

set_required(key, required=True)[source]

Enable or disable the “required” flag for a given field.

When a field is marked required, a value must be provided or else it fails validation.

In practice if a field is “not required” then a default “empty” value is assumed, should the user not provide one.

See also is_required(); this is tracked via required_fields.

Parameters:
  • key – String key (fieldname) for the field.

  • required – New required flag for the field. Usually a boolean, but may also be None to remove any flag and revert to default behavior for the field.

set_validator(key, validator)[source]

Set/override the validator for a field, or the form.

Parameters:
  • key – Name of field. This may also be None in which case the validator will apply to the whole form instead of a field.

  • validator

    Callable which accepts (node, value) args. For instance:

    def validate_foo(node, value):
        if value == 42:
            node.raise_invalid("42 is not allowed!")
    
    form = Form(fields=['foo', 'bar'])
    
    form.set_validator('foo', validate_foo)
    

Validator overrides are tracked via validators.

set_widget(key, widget, **kwargs)[source]

Set/override the widget for a field.

You can specify a widget instance or else a named “type” of widget, in which case that is passed along to make_widget().

Parameters:
  • key – Name of field.

  • widget – Either a deform.widget.Widget instance, or else a widget “type” name.

  • **kwargs – Any remaining kwargs are passed along to make_widget() - if applicable.

Widget overrides are tracked via widgets.

validate()[source]

Try to validate the form, using data from the request.

Uses get_form_data() to retrieve the form data from POST or JSON body.

If the form data is valid, the data dict is returned. This data dict is also made available on the form object via the validated attribute.

However if the data is not valid, False is returned, and there will be no validated attribute. In that case you should inspect the form errors to learn/display what went wrong for the user’s sake. See also get_field_errors().

This uses deform.Field.validate() under the hood.

Warning

Calling validate() on some forms will cause the underlying Deform and Colander structures to mutate. In particular, all readonly_fields will be removed from the schema to ensure they are not involved in the validation.

Returns:

Data dict, or False.

property vue_component

String name for the Vue component, e.g. 'WuttaForm'.

This is a generated value based on vue_tagname.