Model » History » Version 5
Version 4 (Elmer de Looff, 2011-09-20 18:41) → Version 5/28 (Elmer de Looff, 2011-09-20 18:43)
h1. Database abstraction model
h2. Goal of this component
The µWeb framework provides a @model@ module with the intention of simplifying database access. The design goal is to provide a rich abstraction that
* takes away the tedious work of retrieving, creating and deleting records
* can load its parent objects automatically if so required
* _does *not* get in the way of the developer_
Making database interaction easier without restricting the abilities of the developer is our main goal. Some default mechanisms make assumptions on the way the database is organised, but these are well-documented, and it's entirely possible to change the behavior of these mechanisms.
h2. Using the Record
The basic idea of the @Record@ class is that it is a container for your database records, with related records automatically loaded as needed, and custom methods that provide more info, child objects, etc. Outlined below are the default features available, with minimal configuration requirements.
h3. Basic Record usage
There are a few ways to use the @Record@ class. The direct way to create a @Record@ is to initiate it with a connection, and a dictionary of @field -> value@ information. The @Record@ is a dictionary subclass that largely copies all the functionality of a dictionary. Retrieving values for keys works exactly as you'd expect.
h3. Creating your own @Record@
To create your own @Record@ subclass, nothing is required beyond the class name. The following example substitutes a complete working example:
<pre><code class="python">
from underdark.uweb import model
class Message(model.Record):
"""Abstraction class for messages stored in the database."""
</code></pre>
This is the minimum required scaffolding required to abstract a database table. The @_FOREIGN_KEY@ class constant is required, (index, not required, but advisable in general) for the table. This fieldname is used to automatically look up a record if it is referenced and requested elsewhere.
h3. Primary field definition
The @Record@ requires that a table has a single-field unique column. It's advisable for this to be a PRIMARY index in the database, though this is not required. This field is used to automatically look up a record if it is referenced and requested elsewhere.
By default, this primary key field is assumed to be @ID@. If this is not the case for your table, you can easily change this by defining the @_PRIMARY_KEY@ class constant:
<pre><code class="python">
from underdark.uweb import model
class Country(model.Record):
"""Abstraction class for a country table.
This class uses the ISO-3166-1 alpha2 country code as primary key.
"""
_PRIMARY_KEY = 'alpha2'
</code></pre>
h3. Class and table relation
By default, the assumption is made that the table name is the same as the class name, with the first letter lowercase. *The table related to the class @Message@ would be @message@.* To change this behavior, assign the correct table name to the @_TABLE@ class constant. This new table name will then be used in all built-in Record methods:
<pre><code class="python">
from underdark.uweb import model
class Message(model.Record):
"""Abstraction class for messages stored in the database."""
_TABLE = 'MyMessage'
</code></pre>
h3. Alternative initializers
*N.B.* In the default implementation, fields that refer to a record in another table (@n to 1@ or @1 to 1@ relationships) *MUST have the name of that table.*
For example: Given two tables `child` and `parent`. Entries in `child` that refer to their parent, must do so using a field called `parent` (not parentID or some such). If the table names are plural, the fields that refer to the relation should also have a pluralized name.
h2. Goal of this component
The µWeb framework provides a @model@ module with the intention of simplifying database access. The design goal is to provide a rich abstraction that
* takes away the tedious work of retrieving, creating and deleting records
* can load its parent objects automatically if so required
* _does *not* get in the way of the developer_
Making database interaction easier without restricting the abilities of the developer is our main goal. Some default mechanisms make assumptions on the way the database is organised, but these are well-documented, and it's entirely possible to change the behavior of these mechanisms.
h2. Using the Record
The basic idea of the @Record@ class is that it is a container for your database records, with related records automatically loaded as needed, and custom methods that provide more info, child objects, etc. Outlined below are the default features available, with minimal configuration requirements.
h3. Basic Record usage
There are a few ways to use the @Record@ class. The direct way to create a @Record@ is to initiate it with a connection, and a dictionary of @field -> value@ information. The @Record@ is a dictionary subclass that largely copies all the functionality of a dictionary. Retrieving values for keys works exactly as you'd expect.
h3. Creating your own @Record@
To create your own @Record@ subclass, nothing is required beyond the class name. The following example substitutes a complete working example:
<pre><code class="python">
from underdark.uweb import model
class Message(model.Record):
"""Abstraction class for messages stored in the database."""
</code></pre>
This is the minimum required scaffolding required to abstract a database table. The @_FOREIGN_KEY@ class constant is required, (index, not required, but advisable in general) for the table. This fieldname is used to automatically look up a record if it is referenced and requested elsewhere.
h3. Primary field definition
The @Record@ requires that a table has a single-field unique column. It's advisable for this to be a PRIMARY index in the database, though this is not required. This field is used to automatically look up a record if it is referenced and requested elsewhere.
By default, this primary key field is assumed to be @ID@. If this is not the case for your table, you can easily change this by defining the @_PRIMARY_KEY@ class constant:
<pre><code class="python">
from underdark.uweb import model
class Country(model.Record):
"""Abstraction class for a country table.
This class uses the ISO-3166-1 alpha2 country code as primary key.
"""
_PRIMARY_KEY = 'alpha2'
</code></pre>
h3. Class and table relation
By default, the assumption is made that the table name is the same as the class name, with the first letter lowercase. *The table related to the class @Message@ would be @message@.* To change this behavior, assign the correct table name to the @_TABLE@ class constant. This new table name will then be used in all built-in Record methods:
<pre><code class="python">
from underdark.uweb import model
class Message(model.Record):
"""Abstraction class for messages stored in the database."""
_TABLE = 'MyMessage'
</code></pre>
h3. Alternative initializers
*N.B.* In the default implementation, fields that refer to a record in another table (@n to 1@ or @1 to 1@ relationships) *MUST have the name of that table.*
For example: Given two tables `child` and `parent`. Entries in `child` that refer to their parent, must do so using a field called `parent` (not parentID or some such). If the table names are plural, the fields that refer to the relation should also have a pluralized name.