Developer Guidelines | S3ReusableField
Table of Contents
S3ReusableField
S3ReusableField
is a DRY helper class for re-usable Field
definitions.
Define a S3ReusableField
A S3ReusableField
is to be defined like a normal Field (though outside any Table
definitions):
person_id = S3ReusableField("person_id", "reference pr_person", sortby = ["first_name", "middle_name", "last_name"], requires = IS_NULL_OR(IS_ONE_OF(db, "pr_person.id", person_represent, orderby="pr_person.first_name", sort=True, error_message="Person must be specified!")), represent = pr_person_represent, label = T("Person"), comment = pr_person_id_comment, ondelete = "RESTRICT", widget = S3PersonAutocompleteWidget())
This definition does not create a Field
instance, but just holds the parameters.
Use S3ReusableFields in Table Definitions
To use this in a Table
definition, just call the S3ReusableField
object to generate a Field
instance:
tablename = "mytable" self.define_table(tablename, ..., # Insert a Field("person_id") with the pre-defined parameters: person_id(), ...)
Note: If the S3ReusableField
contains the sortby
attribute, then a FieldS3
instance is generated instead of Field
Override Field Attributes
You can override the name and any attributes when generating the Field
instance, by just re-specifying them:
tablename = mytable" self.define_table(tablename, ..., # Insert a Field("reporter") with the attributes from person_id: person_id("reporter", # also override the label: label=T("Reporter"), ), ...)
Deactivate IS_EMPTY_OR
To deactivate an IS_EMPTY_OR
validator in the S3ReusableField
when generating the Field
instance, you can use the special attribute empty
:
tablename = "my_table" self.define_table(tablename, ..., # Inserts the person_id Field, but remove IS_EMPTY_OR from .requires: person_id(empty=False), ...)
Multiple Widgets
Besides the normal "widget" attribute to specify a form widget for the resuable field, it is also possible to specify multiple possible widget alternatives, and then apply them in the instances by name.
To do so, use the "widgets" (plural!) attribute.
Example:
organisation_id = S3ReusableField("organisation_id", "reference org_organisation", requires = IS_EMPTY_OR(IS_ONE_OF(db, "org_organisation.id", org_organisation_represent)), represent = org_organisation_represent, label = T("Organisation"), widgets = {"default": S3OrganisationAutocompleteWidget(default_from_profile=True), "hierarchical": S3HierarchyWidget(lookup = "org_organisation", represent = org_organisation_represent, multiple = False, leafonly = False, ), }, )
Without override or explicit choice, the "default" widget would be used in Field instances.
NB: one should avoid having both "widget" and "widgets" in the same S3ReusableField. However, where both are present, "widget" overrides the "default" alternative in "widgets".
To choose a widget by name:
tablename = "my_table" self.define_table(tablename, ..., # Choose the "hierarchical" widget for this instance: organisation_id(widget="hierarchical"), ... )
This is especially useful if the choice of the widget depends on a deployment setting.
However, every instance can still override all possible alternatives:
tablename = "my_table" self.define_table(tablename, ..., # Specify the widget explicitly: organisation_id(widget=MyCustomWidget()), ... )
...or enforce the web2py standard widget for the field type:
tablename = "my_table" self.define_table(tablename, ..., # Enforce web2py standard widget for the field type: organisation_id(widget=None), ... )