Commit 6e166c72 authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Update help.py to add get_foreign_field_from_reference.

parent ce489e1a
......@@ -22,6 +22,7 @@ from gluon.validators import (IS_DATE_IN_RANGE,
IS_LENGTH)
GIT = "/usr/bin/git"
REX_REFERENCE = re.compile("^reference (\w+)$")
STOREID = "%sStore"
VERSION = "VERSION"
......@@ -321,64 +322,74 @@ def get_file_paths(path, ext=None, alpha=True):
def get_foreign_field(field):
"""Get a tuple with the reference table name, reference field name and
reference primary key name, for the ``field``.
"""Get reference table, field, and primary key names.
Args:
field (gluon.dal.Field): database field
Returns:
tuple:
* ``(k_tablename, k_fieldname, k_keyname)``
* ``k_tablename`` is the name of the reference table
* ``k_fieldname`` is the name of the reference field, *e.g.*
``table.field`` S{->} ``k_table.k_field``
* ``k_keyname`` is the name of the primary key of the
reference table. It is requires by the left join,
``table.field == k_table.k_key``.
In almost all case ``k_key`` is equal to ``id``.
* ``k_tablename`` name of the reference table
* ``k_fieldname`` name of the reference field
* ``k_keyname`` name of the primary key of the reference table.
* ``None`` for standard field.
"""
if not is_foreign_field(field):
return None
# foreign field validators IS_IN_BD contains all information
# foreign field validator IS_IN_BD contains all information
# on the parent key for the left join and on the parent field
validators = as_list(field.requires)
# Several syntax are allowed
# IS_IN_DB is use.
for vdt in validators:
if isinstance(vdt, IS_IN_DB):
if not isinstance(vdt, IS_IN_DB):
continue
# IS_IN_DB contains only the parent field.
# The key for the left join is the id key of the parent table
if len(vdt.fieldnames) == 1:
return (vdt.ktable, vdt.fieldnames[0], "id")
nfields = len(vdt.fieldnames)
if nfields == 1 and vdt.kfield != "id":
return (vdt.ktable, vdt.kfield, "id")
# IS_IN_DB contains the key for the join and the parent field
else:
return (vdt.ktable, vdt.fieldnames[0], vdt.fieldnames[1])
elif nfields == 1 and vdt.kfield == "id":
return get_foreign_field_from_reference(field)
else:
return (vdt.ktable, vdt.fieldnames[0], vdt.fieldnames[1])
# IS_IN_DB is not use.
# The parent key for the left join is the id key of the parent table
# the parent field is the first field of the parent table which differs id
i = field.type.index(" ")
ktablename = field.type[i:].strip()
# extract information from the field type, i.e `reference tablename`
# the parent field is the first field of the parent table which is not id
return get_foreign_field_from_reference(field)
def get_foreign_field_from_reference(field):
"""Get reference table name, reference field name from filed type.
Args:
field (gluon.dal.Field): database field
Returns:
tuple:
* ``k_tablename`` name of the reference table
* ``k_fieldname`` name of the reference field
* ``k_keyname`` name of the primary key of the reference table
Raise:
Exception:
ValueError:
the field name does not match "reference tablename"
"""
mtch = REX_REFERENCE.match(field.type)
if mtch is None:
raise ValueError("field type is not 'reference tablename'")
ktablename = mtch.group(1)
for kfield in field._db[ktablename]:
if kfield.name != "id":
return (ktablename, kfield.name, "id")
raise Exception
def get_id(table, **kwargs):
"""Get the ``id`` of the record identified by a set of ``field=value``
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment