3. Service developers

Keep ModWeb specific learning curve as low as possible: Focus on existing languages and technologies that programmers already know and introduce as few own as possible. A minimal set of skills are needed: Python, XHTML, CSS, SQL (and optionally EcmaScript) are already enough to create a full application with WWW user interface.

  • support web-heads for scalability: sessions are stored in common SQL-database.
  • don’t differentiate desktop- and mobile content:
    • keep the same URLs for reference: referral can’t know what device is used to consume.
    • terminal capabilites
  • ease PKI-deployment in user management
    • support different national id-cards out-of-the-box with ease
  • provide graphical user interface for workstation for server management
  • use XML as internal format when appropriate. Easy machine readability and can be validated

3.1. WSGI framework

Narrow API, find a page class, create an instance of it with arguments and make a string representation of it as a page.

  • wsgi API
  • base template API
  • use templates
  • allow chainloading templates
    • utlize department look-n-feel while allow local site customization
  • split code into functional blocks per directory
  • split application logic and content format layout
  • detect used terminal and bind it to its capabilities
  • provide terminal capabilities for content formatting
  • support multiple content format templates
  • provide capabilities (screen size, image,video format support) for content layouting
  • allow application installation by dropping it into apps/ subdirectory
  • provide automatic and flexible menu engine for web-pages
  • start http-session in first visit. separate http-session from login.
  • provide session storage for non-persistent storage.
  • validate output as much as possible, considering the performance (results post-delivered)

Apache configuration (before the GUI has been fully implemented)

WSGIDaemonProcess modweb.org processes=2 threads=15 display-name=%{GROUP} shutdown-timeout=15 python-path=/srv/
WSGIProcessGroup modweb.org
WSGIScriptAlias / /usr/lib64/python2.6/site-packages/modweb/wsgi/main.wsgi

3.2. Database Authentication

File /var/lib/modweb/httpd.conf contains:

SetEnv SES_DB_HOST "localhost"
SetEnv SES_DB_PORT "5432"
SetEnv SES_DB_NAME "modweb"
SetEnv SES_DB_USER "role_mwses"
SetEnv SES_DB_PASS "abc456"

Include "/var/lib/modweb/example.com/httpd.conf"

File /var/lib/modweb/example.com/httpd.conf contains:

SetEnv DB_HOST "localhost"
SetEnv DB_PORT "5432"
SetEnv DB_NAME "example"
SetEnv DB_USER "role_example_web"
SetEnv DB_PASS "abc789"

And site specific template file /srv/www/example.com/sitecode.py contains:

self.db = DB(

3.3. ORM

ORM (Object Relational Mapper) coming with ModWeb implements an easy to use database abstration that minimizes the application implementation effort related to SQL-database. It aims to provide an interface to RDBMS-database that doesn’t introduce added complexity to normal python object oriented programming and follows pythonic syntax as much as possible.

In other hand, when using ia SQL-datatabase, it’s practically impossible to avoid manipulating the database via SQL-interpreter and hence master the SQL-dialect for given database. Addmitting this and respecting the database developeras’ aim to provide a good database engine, ModWeb ORM does not define the database schema in Python, but instead reads it from used database itself. With this approach, duplicate OOP-model definitions are avoided and also management problems raising when duplicating data (update,delete) into different locations (a common RDBMS problem solved by data de-duplication and normalization).

A typical problem with projects that utilize a RDBMS-database, is scarce skills and manhours available to maintain the part that covers the database functionality, which then appears as lack of proper features that ensures stored data validity. Often that functionality may be impossible to add later because of design errors in code that either would break or prevent enforcing those feaatures (constraints etc). Having these features as part of mandatory implementation feature as describing the object relationships and overall schema layout tackles both problems at once.

Tables represent Python classes, table rows are converted to object instances and table columns are object attributes. Objects are accessed through a list abstraction, a set of rows form database table.

Writing to database is simple, assigning a value to object’s attribute, that will instantly write it into database.

Supported features:

  • inserting: a new database table object creation
  • reading: table object to Python object coversion
  • updating: writing a new attribute value to existing object if it has changed
  • deleting: deleting an object in python causes given database row be deleted
  • hierarchial, multi level object trees with configurable depth
  • transparent attribute types are mapped to python native types
    • integer, string
    • date
  • complex attribute values:
    • object awareness: if object is assigned in Python, its PRIMARY KEY is used automatically
    • python list is normalized into child table with SQL-constraints

These features make ModWeb ORM learning curve very low or non existing. Small amount need code lines makes it productive and focus remains in the actual project code instead of writing and debugging database manipulation code.

  • do not repeat SQL datatype definitions in python when those must be stored in DB itself.
  • enforce database constraints by depending on them
  • each table has a row-id SERIAL type column, rid which is hardcoded and mandatory.
  • Object-to-Relation mapping is done in python class definition.
  • class definition is used to initialize ModWeb-object when accessed via list abstration


Many of the easy-to-use features are based on advanced features of SQL database, features that don’t exist in every SQL database. Hence it’s likely that porting ModWeb ORM to for example MySQL variant is not possible.

If object has attributes that are list-type, those are stored into normalized tables and require FOREIGN KEY constraints to work. If the list .append() method is used, the parent table FOREIGN KEY constraint must have ON DELETE CASCADE switch on, as it is used to detect which table is the parent table.

>>> ALTER TABLE bbb ADD CONSTRAINT aaa_related_fkey
        FOREIGN KEY (b) REFERENCES aaa(rid)

3.3.1. pgdb

Module modweb.core.pgdb is Postgresql implementation of ModWeb ORM.

class modweb.core.pgdb.PostgresqlBase(host, port, db, user=None, pwd=None)
PostgresqlBase is a base class that initializes database connection and provides database handle (self.dbh) and -cursor (self.dbc).
class modweb.core.pgdb.DBTableBase(dbh, rid=None, apiver=1, new=False, uuid=None, depth=2, preInit=True, postInit=True, noInit=False, orderList=[], debug=0, **kwargs)

Base SQL table and Python class abstractor.

param attributes:

normaliZe() keysToInstace()

key2Instance(columnName, classDefinition)
class modweb.core.pgdb.ObjListBase(dbh, depth=2, debug=0, **kwargs)

Object list is intended to be a base of list that can be used in each SQL table based lists that eventually turn into Python objects. Typically this list could be part of some object, like an invoice and its item list. Invoice itself would be an object and it would contain certain metadata and list of item instance objects that are related to product objects they represent.

Benefit of using a list class is faster queries when it can directly, internally create those object instances from single SQL query instead of first querying table keys and then making one query per item instance to create a object with DBTableBase class.

Has payload attribute that is a python List where query results reside. Keys are object rid numbers. If the payload is not object but list of objects, the list is stored into first any only key 0.

Any listobject attribute can be given as kwargs and it will be used as search criteria.


Class names are subject to change, they evolved during the development and do not reflect a logical set of names as end result.

3.4. Example use

Python class and database table wrapping

from modweb.core.pgdb import PostgresqlBase,DBTableBase,ObjListBase

class Organization(PostgresqlBase, DBTableBase, object):
    def __init__(self, dbh, **kwargs):
        self.tableName = 'organizations'
        self.attributes = [ 'uuid', 'name', 'fullname' ]

class Product(PostgresqlBase, DBTableBase, object):
    def __init__(self, dbh, **kwargs):
        self.tableName = 'products'
        self.attributes = [ 'uuid', 'code', 'name' 'manufacturer', ]
        self.normalize('summary', 'product_summary', 'summary')
        self.normalize('related', 'product_related', 'related, 'product')
        self.keyToInstance('manufacturer', Organization)

class ProductList(ObjListBase):
    def __init__(self, **kwargs):

class Database(PostgresqlBase):
    def __init__(self, host, port, db, user, pwd):
        PostgresqlBase.__init__(self, host, port, db, user, pwd)

    def Organization(self, new=True, **kwargs):
        return Organization(dbh=self.dbh, new=True, **kwargs)

    def Product(self, new=True, **kwargs):
        return Product(dbh=self.dbh, new=True, **kwargs)

    def getProducts(self, **kwargs):
        return ProductList(self, **kwargs)

if __name__ == "__main__":

    db = Database(host='localhost', port=5432, db='test1', user='role_user1', pwd='abc123')

    # Creating a new organization object
    o = db.Organization(new=True)
    o.uuid = 'acb0c286-1965-4db5-ac1c-e0f43c909b84'
    o.name = 'Rohde & Schwarz'
    o.fullname = 'Rohde & Schwarz Gmbh'

    # NOT NULL column constraints, must insert at initialization
    p1 = db.Product(name='', summary='Spectrum analyzer')
    p1.manufacturer = o

    p2 = db.Product(name='', summary='Spectrum analyzer')
    p2.manufacturer = o

    # reading a single entry and updating it
    (rs,) = db.getProducts(uuid='acb0c286-1965-4db5-ac1c-e0f43c909b84')
    rs.fullname = 'Keysight'

    # All writings are done already, but close connections too.

In given example, the ModWeb library classes are imported. Two application base objects are defined, Orgnization and Product. Product-class is composed of three SQL-tables, roducts, product_summaries, product_related which all have to be linked together with SQL-constraints. Since related table contains the same objects than main table (it links back), it has to have fourth argument, the pointer column name product.

Table Of Contents

Previous topic

2. System Administrators

Next topic

4. ModWeb developers

This Page