I'm very interested on dynamic model and I'm investigating a little bit.
I've had some results with this model.
The user can define compound models. Types are ancestor types (string,
integer etc) useful for representation
db.define_table(
'types',
Field('type', 'string'),
format='%(type)s'
)
db.define_table(
'models',
Field('name', 'string'),
format='%(name)s'
)
db.define_table(
'models_tree',
Field('parent', 'reference models'),
Field('child', 'reference models'),
Field('display_order', 'integer')
)
db.define_table(
'fields',
Field('name', 'string'),
Field('label', 'string'),
Field('model', 'reference models'),
Field('type', 'reference types'),
Field('display_order', 'integer'),
format='%(name)s'
)
#db.fields.type.requires=IS_IN_DB(db, db.types)
db.define_table(
'rows',
Field('model', 'reference models'),
Field('note', 'text')
)
db.define_table(
'meta',
Field('field', 'reference fields'),
Field('row', 'reference rows'),
Field('value', 'text')
)
db.meta.field.requires=IS_IN_DB(db, db.fields)
db.meta.row.requires=IS_IN_DB(db, db.rows)
def get_models():
query = (db.fields.type == db.types.id) & (db.fields.model ==
db.models.id)
return db(query).select()
models = lambda : get_models()
def get_tree():
parents = db.models.with_alias('parents')
childs = db.models.with_alias('childs')
query = ((db.models_tree.parent == db.models.id) & (db.models_tree.child
== childs.id))
sql = """
SELECT
parents.name,
childs.name
FROM
models as parents,
models as childs,
models_tree
WHERE
models_tree.parent = parents.id AND
models_tree.child = childs.id;
"""
return db.executesql(sql)
def get_fields_from_parent_model(parent_id):
query = db.models_tree.parent == parent_id
models = db(query).select(orderby=db.models_tree.display_order)
fields = []
if models:
for m in models:
fields += get_fields_from_parent_model(m.child)
else:
fields = [r for r in
db(db.fields.model==parent_id).select(orderby=db.fields.display_order)]
return fields
tree = lambda : get_tree()
def build_query(model_id):
fields = get_fields_from_parent_model(model_id)
_select_tpl = "\t%(name)s.value as %(name)s"
_from_tpl = "\t\tJOIN meta %(name)s ON (%(name)s.row = rows.id AND
%(name)s.field = %(id)s)"
_select = ["rows.id as id"]
_from = [" FROM", "\tmodels, ", "\trows"]
for f in fields:
f.name = f.name.replace(" ", "_")
_select.append( _select_tpl % f)
_from.append( _from_tpl % f)
select = 'SELECT '
select += ", ".join(_select)
frm = "\n".join(_from)
#where = " WHERE rows.id = %s;" % row_id
where = " WHERE rows.model = models.id AND models.id = %s" % model_id
sql = select + frm + where
print sql
rows = db.executesql( sql )
return rows