Forms

Add a New Form

Configuration

To configure a normal form, you subclass the ModelForm. On this subclass there are several options you can/must override. The mandatory options are listed first, followed by a list of optional configuration parameters. Finally, you can of course always override the methods on the form.

class pyramid_crud.forms.ModelForm(formdata=None, obj=None, *args, **kw)[source]

Base-class for all regular forms.

The following configuration options are available on this form in addition to the full behavior described for WTForms-Alchemy

Note

While this class can easily be the base for each form you want to configure, it is strongly recommended to use the CSRFModelForm instead. It is almost no different than this form except for a new csrf_token field. Thus it should never hurt to subclass it instead of this form.

Meta
This is the only mandatory argument. It is directly taken over from WTForms-Alchemy so you should check out their documentation on this class as it will provide you with a complete overview of what’s possible here.
inlines
A list of forms to use as inline forms. See Inline Forms / One-To-Many.
fieldsets

Optionally define fieldsets to group your form into categories. It requires a list of dictionaries and in each dictionary, the following attributes can/must be set:

  • title: A title to use for the fieldset. This is required but may be the empty string (then no title is displayed).
  • fields: A list of field names that should be displayed together in a fieldset. This is required.
  • template: The name of the fieldset template to load. This must be the name of a file in the fieldsets directory of the current theme without a file extension. It defaults to horizontal which uses bootstraps horizontal forms for each fieldset. See Fieldset Templates for details on available templates.
title
Set the title of your form. By default this returns the class name of the model. It is used in different places such as the title of the page.
title_plural:
The plural title. By default it is the title with an “s” appended, however, you somtimes might want to override it because “Childs” just looks stupid ;-)
name:
The name of this form. By default it uses the lowercase model class name. This is used internally und you normally do not need to change it.
get_dbsession:
Unfortunately, you have to define this classmethod on the form to get support for the unique validator. It is documented in Unique Validator. This is a limitation we soon hope to overcome.
fieldsets

See inline documentation for ModelForm

get_fieldsets()

Get a list of all configured fieldsets, setting defaults where they are missing.

populate_obj(obj)[source]

Populates the attributes of the passed obj with data from the form’s fields.

Note:This is a destructive operation; Any attribute with the same name as a field will be overridden. Use with caution.
populate_obj_inline(obj)[source]

Populate all inline objects. It takes the usual obj argument that is the parent of the inline fields. From these all other values are derived and finally the objects are updated.

Note

Right now this assumes the relationship operation is a append, thus for example set collections won’t work right now.

primary_keys

Get a list of pairs name, value of primary key names and their values on the current object.

process(formdata=None, obj=None, **kwargs)[source]

Take form, object data, and keyword arg input and have the fields process them.

Parameters:
  • formdata – Used to pass data coming from the enduser, usually request.POST or equivalent.
  • obj – If formdata is empty or not provided, this object is checked for attributes matching form field names, which will be used for field values.
  • data – If provided, must be a dictionary of data. This is only used if formdata is empty or not provided and obj does not contain an attribute named the same as the field.
  • **kwargs – If formdata is empty or not provided and obj does not contain an attribute named the same as a field, form will assign the value of a matching keyword argument to the field, if one exists.
process_inline(formdata=None, obj=None, **kwargs)[source]

Process all inline fields. This sets the global attribute inline_fields which is a dict-like object that contains as keys the name of all defined inline fields and as values a pair of inline, inline_forms where inline is the inline which the name refers to and inline_forms is the list of form instances associated with this inline.

validate()[source]

Validates the form by calling validate on each field, passing any extra Form.validate_<fieldname> validators to the field validator.

validate_inline()[source]

Validate all inline forms. Implicitly called by validate().

This will also fill the form.errors dict with additional error messages based on invalid inline fields using the same naming pattern used for naming inline fields for display and form submission, i.e. inlinename_index_fieldname.

Thus, if errors exist on an inline field, they can be fetched from the global errors dict the same way regular errors are present in it.

Fieldset Templates

You can configure custom fieldset templates on the fieldsets configuration parameter by setting the “template” key for a fieldset. The following fieldsets are available:

horizontal
A typical horizontal display that renders each form field in its own row with a label before the field.
grid
A grid display that renders the field first and then displays the label. All fields are next to each other and line breaks only happen at the edge of the screen. This is a good template for a fieldset that consists only of checkboxes. This will not display the “description” of a field.

Inline Forms / One-To-Many

class pyramid_crud.forms.BaseInLine(formdata=None, obj=None, *args, **kw)[source]

Base-class for all inline forms. You normally don’t subclass from this directly unless you want to create a new inline type. However, all inline types share the attributes inherited by this template.

Inline forms are forms that are not intended to be displayed by themselves but instead are added to the inlines attribute of a normal form. They will then be displayed inside the normal form while editing, allowing for multiple instance to be added, deleted or modified at the same time. They are heavily inspired by Django’s inline forms.

An inline form is configurable with the following attributes, additionally to any attribute provided by WTForms-Alchemy

Meta
This is the standard WTForms-Alchemy attribute to configure the model. Check out their documentation for specific details.
relationship_name

The name of the other side of the relationship. Determined automatically, unless there are multiple relationships between the models in which case this must be overridden by the subclass.

For example: If this is the child form to be inlined, the other side might be called children and this might be called parent (or it might not even exist, there is no need for a bidrectional relationship). The correct value would then be children not parent.

extra
How many empty fields to display in which new objects can be added. Pay attention that often fields require intputs and thus extra field may often not be left empty. This is an intentional restriction to allow client-side validation without javascript. So only specify this if you are sure that items will always be added (note, however, that the extra attribute is not used to enforce a minimum number of members in the database). Defaults to 0.
is_extra
A boolean indicating whether this instance is an extra field or a persisted database field. Set during parent’s processing.
fieldsets

See inline documentation for ModelForm

get_fieldsets()

Get a list of all configured fieldsets, setting defaults where they are missing.

classmethod pks_from_formdata(formdata, index)[source]

Get a list of primary key values in the order of the primary keys on the model. The returned value is suitable to be passed to sqlalchemy.orm.query.Query.get().

Parameters:
  • formdata – A webob.multidict.MultiDict that contains all parameters that were passed to the form.
  • index (int) – The index of the element for which the primary key is desired. From this, the correct field name to get from fromdata is determined.
Returns:

A tuple of primary keys that uniquely identify the object in the database. The order is based on the order of primary keys in the table as reported by SQLAlchemy.

Return type:

tuple

populate_obj(obj)

Populates the attributes of the passed obj with data from the form’s fields.

Note:This is a destructive operation; Any attribute with the same name as a field will be overridden. Use with caution.
primary_keys

Get a list of pairs name, value of primary key names and their values on the current object.

process(formdata=None, obj=None, data=None, **kwargs)

Take form, object data, and keyword arg input and have the fields process them.

Parameters:
  • formdata – Used to pass data coming from the enduser, usually request.POST or equivalent.
  • obj – If formdata is empty or not provided, this object is checked for attributes matching form field names, which will be used for field values.
  • data – If provided, must be a dictionary of data. This is only used if formdata is empty or not provided and obj does not contain an attribute named the same as the field.
  • **kwargs – If formdata is empty or not provided and obj does not contain an attribute named the same as a field, form will assign the value of a matching keyword argument to the field, if one exists.
validate()

Validates the form by calling validate on each field, passing any extra Form.validate_<fieldname> validators to the field validator.

class pyramid_crud.forms.TabularInLine(formdata=None, obj=None, *args, **kw)[source]

A base class for a tabular inline display. Each row is displayed in a table row with the field labels being displayed in the table head. This is basically a list view of the fields only that you can edit and delete them and even insert new ones.

Many-To-One & One-To-One

The opposite of the One-To-Many pattern is the Many-To-One. One-To-One looks the same from the “One” side, just that the “parent” does not have many “children” but one “child”.

Both relationships are possible without any further configuration. They are automatically detected and work right away. Currently, this feature only has limited use as you cannot directly create a parent form here. Instead the parent object has to exist. Then you can go back and select it in the child’s edit form.

Note

When using a model with a child as an inline, this automatic detection will not display the parent item in the inline form.

Extra Forms

CSRF

The CSRF Forms are special forms to protect you against CSRF attacks. There are two different types: The CSRFForm is the base for any form that wants to enable CSRF and is not limited to the usage within the scope of this library (it is not integrated with the rest of the system, it only implements a WTForms form that takes a pyramid.request.Request as the csrf_context). The CSRFModelForm on the other hand is integrated with the rest of the library and should be used to protect a form against CSRF attacks while still maintaining the complete functionality of the ModelForm.

class pyramid_crud.forms.CSRFForm(formdata=None, obj=None, prefix=u'', csrf_context=None, **kwargs)[source]

Base class from which new CSRF-protected forms are derived. Only use this if you want to create a form without the extra model-functionality, i.e. is normal form.

If you want to create a CSRF-protected model form use CSRFModelForm.

generate_csrf_token(csrf_context)[source]

Create a CSRF token from the given context (which is actually just a pyramid.request.Request instance). This is automatically called during __init__.

validate()[source]

Validate the form and with it the CSRF token. Logs a warning with the error message and the remote IP address in case of an invalid token.

class pyramid_crud.forms.CSRFModelForm(formdata=None, obj=None, *args, **kw)[source]

A form that adds a CSRF token to the form. Derive from this class for security critical operations (read: you want it most of the time and it doesn’t hurt).

Do not derive from this for inline stuff and other composite forms: Only the main form should use this as you only need one token per request.

All configuration is done exactly in the same way as with the ModelForm except for one difference: An additional csrf_context argument is required. The pre-configured views and templates already know how to utilize this field and work fine with and without it.

Fields

The library defined some special fields. Normally, there is no need to be concerned with them as they are used internally. However, they might provide useful features to a developer.

class pyramid_crud.fields.MultiCheckboxField(label=None, validators=None, coerce=<type 'unicode'>, choices=None, **kwargs)[source]

A multiple-select, except displays a list of checkboxes.

Iterating the field will produce subfields, allowing custom rendering of the enclosed checkbox fields.

Example for displaying this field:

class MyForm(Form):
    items = MultiCheckboxField(choices=[('1', 'Label')]
form = MyForm()
for item in form.items:
    str(item)  # the actual field to be displayed, likely in template

If you don’t iterate, it produces an unordered list be default (if str is called on form.items, not each item individually).

And with formdata it might look like this:

# Definition same as above
formdata = MultiDict()
formdata.add('items', '1')
form = MyForm(formdata)
assert form.items.data == ['1']

As you can see, a list is produces instead of a scalar value which allows multiple fields with the same name.

class pyramid_crud.fields.MultiHiddenField(label=None, validators=None, coerce=<type 'unicode'>, choices=None, **kwargs)[source]

A field that represents a list of hidden input fields the same way as MultiCheckboxField and wtforms.fields.SelectMultipleField.

class pyramid_crud.fields.SelectField(label=None, validators=None, coerce=<type 'unicode'>, choices=None, **kwargs)[source]

Same as wtforms.fields.SelectField with a custom validation message and the requirement that data evaluates to True (for the purpose of having an empty field that is not allowed).