"""
:mod:`zsl.db.helpers.nested`
----------------------------
.. moduleauthor:: Peter Morihladko <morihladko@atteq.com>
"""
from typing import Any, Optional
from sqlalchemy.orm.attributes import InstrumentedAttribute
from zsl.db.model.app_model import AppModel
from zsl.db.model.raw_model import ModelBase
[docs]
def get_nested_field_name(field):
if isinstance(field, InstrumentedAttribute):
field = field.property.key
return field
[docs]
def nested_model(model, nested_fields):
# type: (ModelBase, Any)->Optional[AppModel]
"""
Return :class:`zsl.db.model.app_model import AppModel` with the nested
models attached. ``nested_fields`` can be a simple list as model
fields, or it can be a tree definition in dict with leafs as keys with
``None`` value
"""
if model is None:
return None
app_model = model.get_app_model()
is_dict = isinstance(nested_fields, dict)
for field in nested_fields:
field = get_nested_field_name(field)
nested_nested = nested_fields.get(
field) if is_dict and nested_fields.get(field) else []
value = getattr(model, field, None)
# we can have also lists in field
nm_fn = nested_models if isinstance(value, list) else nested_model
setattr(app_model, field, nm_fn(value, nested_nested))
return app_model
[docs]
def nested_models(models, nested_fields):
"""For a list of ``models`` apply ``get_nested_model`` with given
``nested_fields``.
"""
return [nested_model(model, nested_fields) for model in models]