|Version 10 (modified by 10 years ago) ( diff ),|
Table of Contents
S3Model class defines the framework for data models in Eden. It extends the web2py concept by:
- implicit and lazy model loading
- an extensible, per-table configuration pattern
- a meta-model for projected entities (the so-called "resource component model")
- a meta-model for multi-table keys (the so-called "super-entity model")
Data models can be implemented as subclasses of S3Model, and then loaded on demand - with automatic resolution of cross-model dependencies. This saves processing time as it will always only load those models which are actually needed to process the request.
S3 data models reside in
The file name of each Python module in
modules/s3db corresponds to the Eden module prefix. All names with this prefix will be looked up from this file.
- Tablename: org_office => Module Prefix: "org" => Looked up from: modules/s3db/org.py
All S3 data models need to be imported in models/00_tables.py:
import s3db.assess import s3db.asset import s3db.auth import s3db.cap ...
Every Python module in modules/s3db must have an
__all__ statement declaring the classes and functions to be imported:
__all__ = ["S3DeploymentModel", "S3DeploymentAlertModel", "deploy_rheader", "deploy_apply", "deploy_alert_select_recipients", "deploy_response_select_mission", ]
Important: Undeclared classes or functions are not available to the model loader!
All names in
__all__ starting with the module prefix (e.g.
deploy_) can be accessed globally with
current.s3db.deploy_apply), without need to import them explicitly.
Every data model is defined as a subclass of S3Model:
All names from the model which shall be globally accessible (i.e. tables, functions, variables, classes) must be declared in the names-variable:
class S3DeploymentModel(S3Model): names = ["deploy_event_type", "deploy_mission", "deploy_mission_id", "deploy_mission_document", "deploy_application", "deploy_assignment", "deploy_assignment_appraisal", "deploy_assignment_experience", ]
These names can then be accessed via
Important: All table names and names which are returned from a model class must use the module prefix (otherwise they can't be found).
S3Model subclass must implement the model() function. This function defines all tables, functions and variables of the model:
class S3DeploymentModel(S3Model): ... def model(self):
To define a table, the model() function must use
self.define_table (instead of
def model(self): tablename = "deploy_mission" table = self.define_table(tablename, ...)
The model function must return a dict with the definitions of all names as declared in the
names class-variable (except table names):
class MyModel(S3Model): names = ["my_function", "my_variable"] def model(self): my_variable = "example" return dict(my_own_function = self.my_function my_variable = my_variable ) @staticmethod def my function(): ... return
Ideally, custom functions in model classes which are returned from model() should be declared @staticmethod or @classmethod to allow the instance to be garbage-collected (i.e. release the thread-global pointer to the instance from current.s3db).
Every model class should define a
defaults() function which returns safe defaults for the declared names in case the Eden module has been disabled per deployment-settings.
This is particularly important for re-usable fields holding foreign keys to tables defined in this model:
class S3DeploymentModel(S3Model): names = [... "deploy_mission_id", ] def model(self): ... mission_id = S3ReusableField("mission_id", table, ... ) return dict(deploy_mission_id = mission_id) def defaults(self): # Module disabled, define a safe default for "mission_id": mission_id = S3ReusableField("mission_id", "integer", readable=False, writable=False) return dict(deploy_mission_id = mission_id)
S3Model base class implements a number of useful helper functions to implement models, among others:
super_linkto define or reference super entities
add_componentto define resource components
configureto define table configuration settings
These functions should not be overwritten in the subclass.