Skip to content

Commit

Permalink
Merge pull request #44 from ral-facilities/43_allow_many_to_many_incl…
Browse files Browse the repository at this point in the history
…udes

Allow many to many includes
  • Loading branch information
keiranjprice101 authored Sep 11, 2019
2 parents fb16374 + 7ec4f3f commit 82e7dcb
Showing 1 changed file with 38 additions and 6 deletions.
44 changes: 38 additions & 6 deletions common/models/db_models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from sqlalchemy import Index, Column, BigInteger, String, DateTime, ForeignKey, Integer, Float, FetchedValue
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.orm.collections import InstrumentedList

from common.exceptions import BadFilterError

Expand All @@ -25,23 +26,55 @@ def to_dict(self):
def to_nested_dict(self, includes):
"""
Given related models return a nested dictionary with the child or parent rows nested.
:param included_relations: string/list/dict - The related models to include.
:param includes: string/list/dict - The related models to include.
:return: A nested dictionary with the included models
"""
dictionary = self.to_dict()
try:
includes = includes if type(includes) is list else [includes]
for include in includes:
if type(include) is str:
related_entity = self.get_related_entity(include)
dictionary[related_entity.__tablename__] = related_entity.to_dict()
self._nest_string_include(dictionary, include)
elif type(include) is dict:
related_entity = self.get_related_entity(list(include)[0])
dictionary[related_entity.__tablename__] = related_entity.to_nested_dict(include[list(include)[0]])
self._nest_dictionary_include(dictionary, include)
except TypeError:
raise BadFilterError(f" Bad include relations provided: {includes}")
return dictionary

def _nest_dictionary_include(self, dictionary, include):
"""
Given a dictionary of related entities names, nest the related entities into the given dictionary representation,
of the original entity.
:param dictionary: The dictionary representation of the original entity
:param include: The dictionary of related entity names to be nested.
"""
related_entity = self.get_related_entity(list(include)[0])
if not isinstance(related_entity, InstrumentedList):
dictionary[related_entity.__tablename__] = related_entity.to_nested_dict(include[list(include)[0]])
else:
for entity in related_entity:
if entity.__tablename__ in dictionary.keys():
dictionary[entity.__tablename__].append(entity.to_nested_dict(include[list(include)[0]]))
else:
dictionary[entity.__tablename__] = [entity.to_nested_dict(include[list(include)[0]])]

def _nest_string_include(self, dictionary, include):
"""
Given the name of a single related entity, nest the related entity into the given dictionary representation of
the original entity.
:param dictionary: The dictionary representation of an entity to be nested in.
:param include: The name of the related entity to be nested
"""
related_entity = self.get_related_entity(include)
if not isinstance(related_entity, InstrumentedList):
dictionary[related_entity.__tablename__] = related_entity.to_dict()
else:
for entity in related_entity:
if entity.__tablename__ in dictionary.keys():
dictionary[entity.__tablename__].append(entity.to_dict())
else:
dictionary[entity.__tablename__] = [entity.to_dict()]

def get_related_entity(self, entity):
"""
Given a string for the related entity name, return the related entity
Expand Down Expand Up @@ -549,7 +582,6 @@ class JOB(Base, EntityHelper):
backref='JOB')



class KEYWORD(Base, EntityHelper):
__tablename__ = 'KEYWORD'
__table_args__ = (
Expand Down

0 comments on commit 82e7dcb

Please sign in to comment.