Changes between Version 9 and Version 10 of S3/S3Model


Ignore:
Timestamp:
01/16/14 13:33:23 (11 years ago)
Author:
Dominic König
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • S3/S3Model

    v9 v10  
    1818Data 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.
    1919
     20== Defining Models ==
     21
     22=== Modules ===
     23
     24S3 data models reside in {{{modules/s3db}}}.
     25
     26The 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.
     27
     28 '''Example:'''
     29
     30  - ''Tablename'': org_office => ''Module Prefix'': "org" => ''Looked up from'': modules/s3db/org.py
     31
     32All S3 data models need to be imported in models/00_tables.py:
     33
     34{{{#!python
     35import s3db.assess
     36import s3db.asset
     37import s3db.auth
     38import s3db.cap
     39...
     40}}}
     41
     42Every Python module in modules/s3db must have an {{{__all__}}} statement declaring the classes and functions to be imported:
     43
     44{{{#!python
     45__all__ = ["S3DeploymentModel",
     46           "S3DeploymentAlertModel",
     47           "deploy_rheader",
     48           "deploy_apply",
     49           "deploy_alert_select_recipients",
     50           "deploy_response_select_mission",
     51           ]
     52}}}
     53
     54 '''Important:''' Undeclared classes or functions are not available to the model loader!
     55
     56All names in {{{__all__}}} starting with the module prefix (e.g. {{{deploy_}}}) can be accessed globally with {{{current.s3db.<name>}}} (e.g. {{{current.s3db.deploy_apply}}}), without need to import them explicitly.
     57
     58=== Model Classes ===
     59
     60Every data model is defined as a subclass of S3Model:
     61
     62{{{#!python
     63class S3DeploymentModel(S3Model):
     64}}}
     65
     66==== Names ====
     67
     68All names from the model which shall be globally accessible (i.e. tables, functions, variables, classes) must be declared in the names-variable:
     69
     70{{{#!python
     71class S3DeploymentModel(S3Model):
     72
     73    names = ["deploy_event_type",
     74             "deploy_mission",
     75             "deploy_mission_id",
     76             "deploy_mission_document",
     77             "deploy_application",
     78             "deploy_assignment",
     79             "deploy_assignment_appraisal",
     80             "deploy_assignment_experience",
     81             ]
     82}}}
     83
     84These names can then be accessed via {{{current.s3db.<name>}}} (e.g. {{{current.s3db.deploy_mission_id}}}).
     85
     86  '''Important:''' All table names and names which are returned from a model class '''must''' use the module prefix (otherwise they can't be found).
     87
     88==== model() function ====
     89
     90Every {{{S3Model}}} subclass '''must''' implement the model() function. This function defines all tables, functions and variables of the model:
     91
     92{{{#!python
     93class S3DeploymentModel(S3Model):
     94
     95    ...
     96
     97    def model(self):
     98
     99}}}
     100
     101To define a table, the model() function must use {{{self.define_table}}} (instead of {{{current.db.define_table}}}):
     102
     103{{{#!python
     104    def model(self):
     105
     106        tablename = "deploy_mission"
     107        table = self.define_table(tablename,
     108                                  ...)
     109}}}
     110
     111The model function '''must''' return a dict with the definitions of all names as declared in the {{{names}}} class-variable ('''except''' table names):
     112
     113{{{#!python
     114class MyModel(S3Model):
     115
     116    names = ["my_function", "my_variable"]
     117
     118    def model(self):
     119
     120        my_variable = "example"
     121
     122        return dict(my_own_function = self.my_function
     123                    my_variable = my_variable
     124                   )
     125
     126    @staticmethod
     127    def my function():
     128
     129      ...
     130      return
     131
     132}}}
     133
     134Ideally, 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).
     135
     136==== defaults() function ====
     137
     138Every 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.
     139
     140This is particularly important for re-usable fields holding foreign keys to tables defined in this model:
     141
     142{{{#!python
     143class S3DeploymentModel(S3Model):
     144
     145    names = [...
     146             "deploy_mission_id",
     147             ]
     148
     149    def model(self):
     150
     151        ...
     152
     153        mission_id = S3ReusableField("mission_id", table,
     154                                     ...
     155                                     )
     156
     157        return dict(deploy_mission_id = mission_id)
     158
     159    def defaults(self):
     160
     161        # Module disabled, define a safe default for "mission_id":
     162        mission_id = S3ReusableField("mission_id", "integer", readable=False, writable=False)
     163        return dict(deploy_mission_id = mission_id)
     164}}}
     165
     166
     167==== Utility functions ====
     168
     169The {{{S3Model}}} base class implements a number of useful helper functions to implement models, among others:
     170
     171- {{{super_entity}}} and {{{super_link}}} to define or reference super entities
     172- {{{add_component}}} to define resource components
     173- {{{configure}}} to define table configuration settings
     174
     175These functions should not be overwritten in the subclass.
     176
    20177== Concepts ==
    21178