schema.Table: Add add_child_row_location() and friends

Add the following methods:

 add_child_row_location(self, parent_table: Union[Self, str], **kwargs) -> Optional[str]
 add_child_row_location_rules(self) -> Iterable[str]
 add_child_row_location_rule(self, child_table: Union[Self, str]) -> Optional[str]

These are meant to be called from different pieces of code:

 - add_child_row_location() is meant to be used where the parent is
   rendered, to display a link to adding another child

 - add_child_row_location_rules() and add_child_row_location_rule()
   are meant to be invoked where processing is going to be done, i.e.
   likely code rendering child row content

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2025-02-15 16:30:14 +01:00
commit b33d9af302

View file

@ -39,10 +39,11 @@ class Table(abc.ABC): # export
self.__location_rule: Optional[Iterable[str]] = None
self.__row_location_rule: Optional[Iterable[str]] = None
self.__add_row_location_rule: Optional[Iterable[str]] = None
self.___add_child_row_location_rules: Optional[dict[str, str]] = None
self.__foreign_keys_to_parent_table: Optional[OrderedDict[str, Any]] = None
self.__relationships: Optional[list[tuple[str, Self]]] = None
self.__model_class: Optional[Any] = None
self.__relationship_by_foreign_table: Optional[dict[str, Self]] = None
self.___relationship_by_foreign_table: Optional[dict[str, Self]] = None
@property
def __columns(self) -> OrderedDict[str, Any]:
@ -61,6 +62,26 @@ class Table(abc.ABC): # export
self.___foreign_key_parent_tables[cfk.parent_table.name] = cfk.parent_table
return self.___foreign_key_parent_tables
@property
def __relationship_by_foreign_table(self) -> dict[str, Self]:
if self.___relationship_by_foreign_table is None:
ret: dict[str, Self] = dict()
for member_name, table_name in self.relationships:
ret[member_name] = self.schema[table_name]
self.___relationship_by_foreign_table = ret
return self.___relationship_by_foreign_table
@property
def __add_child_row_location_rules(self) -> dict[str, str]:
if self.___add_child_row_location_rules is None:
ret: dict[str, str] = {}
for foreign_table_name, foreign_table in self.__relationship_by_foreign_table.items():
if len(self.foreign_keys_to_parent_table(foreign_table)):
rule = self._add_child_row_location_rule(foreign_table_name)
ret[foreign_table_name] = rule
self.___add_child_row_location_rules = ret
return self.___add_child_row_location_rules
def __len__(self):
return len(self.__columns)
@ -172,6 +193,17 @@ class Table(abc.ABC): # export
def _add_row_location_rule(self) -> Optional[str]:
return self._location_rule() + '/new'
def _add_child_row_location_rule(self, parent_table_name: str) -> Optional[str]:
parent_table = self.schema[parent_table_name]
ret = self._add_row_location_rule()
for cfk in self.foreign_keys_to_parent_table(parent_table):
for fk in cfk:
token = f'/<{fk.child_column.name}>'
if ret.find(token) != -1:
continue
ret += f'/<{fk.child_column.name}>'
return ret
# -- To be used
def column_default(self, name) -> Any:
@ -268,6 +300,27 @@ class Table(abc.ABC): # export
ret = re.sub(f'<{col}>', quote_plus(quote_plus(str(kwargs[col]))), ret)
return ret
@property
def add_child_row_location_rules(self) -> Iterable[str]:
return self.__add_child_row_location_rules.values()
def add_child_row_location_rule(self, child_table: Union[Self, str]) -> Optional[str]:
if isinstance(child_table, Table):
child_table = child_table.name
return self.__add_child_row_location_rules.get(child_table)
def add_child_row_location(self, parent_table: Union[Self, str], **kwargs) -> Optional[str]:
ret = self.add_child_row_location_rule(parent_table)
if isinstance(parent_table, str):
parent_table = self.schema[parent_table]
if ret is None:
return None
for cfk in self.foreign_keys_to_parent_table(parent_table):
for fk in cfk:
if fk.parent_column.name in kwargs:
ret = re.sub(f'<{fk.child_column.name}>', quote_plus(quote_plus(str(kwargs[fk.parent_column.name]))), ret)
return ret
@property
def primary_keys(self) -> Iterable[str]:
if self.__primary_keys is None:
@ -368,7 +421,7 @@ class Table(abc.ABC): # export
self.__foreign_keys_to_parent_table[pt] = []
self.__foreign_keys_to_parent_table[pt].append(cfk)
parent_table_name = parent_table if isinstance(parent_table, str) else parent_table.name
return self.__foreign_keys_to_parent_table[parent_table_name]
return self.__foreign_keys_to_parent_table[parent_table_name] if parent_table_name in self.__foreign_keys_to_parent_table else []
@property
def relationships(self) -> list[tuple[str, Self]]:
@ -382,9 +435,4 @@ class Table(abc.ABC): # export
def relationship(self, table: Union[Self, str]) -> bool:
if isinstance(table, Table):
table = table.name
if self.__relationship_by_foreign_table is None:
ret: dict[str, Self] = dict()
for member_name, table_name in self.relationships:
ret[member_name] = self.schema[table_name]
self.__relationship_by_foreign_table = ret
return self.__relationship_by_foreign_table.get(table)