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 newcsrf_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 thefieldsets
directory of the current theme without a file extension. It defaults tohorizontal
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 ofinline, inline_forms
whereinline
is the inline which the name refers to andinline_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 calledparent
(or it might not even exist, there is no need for a bidrectional relationship). The correct value would then bechildren
notparent
.- 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: - formdata – A
-
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__
.
-
-
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 additionalcsrf_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 onform.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
andwtforms.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 thatdata
evaluates toTrue
(for the purpose of having an empty field that is not allowed).