Table of Contents
By default, S3CRUD generates create/update forms based on introspection of the table: all fields which are set to either readable or writable will be included in the form, in the order in which they are defined in the table.
This default form can be replaced by setting the "crud_form" hook to an instance of S3SQLCustomForm (e.g. in the controller), which allows you to explicitly select the fields and the order in which they appear in the form, and even to include fields from components.
S3CRUD will then use this form definition instead of the default form.
def inline(): from s3.s3forms import S3SQLCustomForm, S3SQLInlineComponent crud_form = S3SQLCustomForm( "first_name", "last_name", S3SQLInlineComponent( "contact", name="test", label=T("Contact Information"), fields=["contact_method", "value"] ), "age_group", "date_of_birth", S3SQLInlineComponent( "note", label=T("Notes"), fields=["timestmp", "note_text"] ), "identification.status" ) s3db.configure("pr_person", crud_form=crud_form) return s3_rest_controller("pr", "person")
S3SQLCustomForm takes instances of subclasses of S3SQLFormElement as parameters. Currently implemented S3SQLFormElement subclasses are:
|S3SQLField||Regular form widget for fields in either the main table or in a subtable (single-record component)|
|S3SQLInlineComponent||A subform for multi-record components|
Strings in the parameter list will be interpreted as field selectors, and used to instantiate S3SQLFields for the fields they address. Note that only fields in the main table or single-record components can be specified this way - everything else will raise a SyntaxError.
The order in which the form elements appear in the parameter list determines the order in which they appear in the form.
Form elements or actions which the user is not permitted to access will be rendered either read-only or not at all (according to the actual permission). The same applies for elements (e.g. components) which are deactivated in the deployment.
Regular fields in the main table can be specified simply by their field name.
crud_form = S3SQLCustomForm( "first_name", "last_name", "age_group", "date_of_birth", )
Fields can be specified in arbitrary order, but must not be repeated within the list.
Fields in Subtables
Fields in components which are set to multiple=False (single-record components = sub-tables) can also be specified as field selector strings using the "."-notation:
crud_form = S3SQLCustomForm( "identification.status" )
Fields from single-record components can be specified anywhere in the form elements list, they do not need to stand together or at a particular place in the field order. However - the same field must not be repeated.
The form element will use the default widget for the respective field in the subtable.
If the user is not permitted to access this component, then the widget will not be rendered at all. If the user has only read access, it will be rendered read-only.
Components with multiple=True (multi-record components) can be specified as instances of S3SQLInlineComponent:
crud_form = S3SQLCustomForm( S3SQLInlineComponent( "contact", name="test", label=T("Contact Information"), fields=["contact_method", "value"] ), S3SQLInlineComponent( "note", label=T("Notes"), fields=["timestmp", "note_text"] ), )
These form elements will be rendered as embedded tables of the existing records in the component with the option to add, update and delete rows (depending on permissions for this components).
The first argument of S3SQLInlineComponent is the resource alias name (usually the tablename without module prefix).
You can also specify a label (title) for the subform using the "label" argument (optional)
The "fields" argument specifies the fields to display in the subform, and the order in which they shall appear. This argument is required.
Filtering of Inline-Components
To filter an inline component by e.g. type, you can a
filterby option like in:
S3SQLInlineComponent( "contact", name="email", label=T("Email Addresses"), fields=["value"], filterby = dict( field = "contact_method", options = "EMAIL" ) ),
The filterby settings is a dict (or a list of dicts for multiple filters), containing:
|field||the name of field to filter by|
|options||the allowed options for this field, a single value or a list of values|
|invert||True to invert this filter (default False)|
|default||default value for this field (if only one option is given and invert is False, then that option will automatically be the default value - unless you specify something else)|
Where multiple sub-forms for the same component (but with different filters) shall be embedded, they must each have a distinct "name" argument. Otherwise this argument is optional.
Sorting of Inline-Components
It is possible to sort the inline-items by specifying an
orderby option with a field selector relative to the component table:
s3forms.S3SQLInlineComponent( "location", label = T("Countries"), fields = ["location_id"], orderby = "location_id$name" ),
To specify a different sort order, the
orderby-option also accepts a tuple like:
s3forms.S3SQLInlineComponent( "location", label = T("Countries"), fields = ["location_id"], orderby = ("location_id$name", "desc") ),
The sort order defaults to "asc".
Note: the field selector used in orderby must give exactly one value per row (i.e. use only forward-links, not component fields or list:types), otherwise the same component item would appear multiple times in the form (due to the left join involved).
Note: the sorting always only affects existing items - new items would still be added at the end of the inline component.