from app import app from flask import json from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm.attributes import QueryableAttribute db = SQLAlchemy(app) class Base(db.Model): __abstract__ = True def to_dict(self, show=None, _hide=[], _path=[]): show = show or [] hidden = self._hidden_fields if hasattr(self, "_hidden_fields") else [] default = self._default_fields if hasattr(self, "_default_fields") else [] default.extend(['id', 'modified_at', 'created_at']) hidden = self._hidden_fields if hasattr(self, "_hidden_fields") else [] default = self._default_fields if hasattr(self, "_default_fields") else [] default.extend(['id', 'modified_at', 'created_at']) if not _path: _path = self.__tablename__.lower() def prepend_path(item): item = item.lower() if item.split(".", 1)[0] == _path: return item if len(item) == 0: return item if item[0] != ".": item = ".%s" % item item = "%s%s" % (_path, item) return item _hide[:] = [prepend_path(x) for x in _hide] show[:] = [prepend_path(x) for x in show] columns = self.__table__.columns.keys() relationships = self.__mapper__.relationships.keys() properties = dir(self) ret_data = {} for key in columns: if key.startswith("_"): continue check = "%s.%s" % (_path, key) if check in _hide or key in hidden: continue if check in show or key in default: ret_data[key] = getattr(self, key) for key in relationships: if key.startswith("_"): continue check = "%s.%s" % (_path, key) if check in _hide or key in hidden: continue if check in show or key in default: _hide.append(check) is_list = self.__mapper__.relationships[key].uselist if is_list: items = getattr(self, key) if self.__mapper__.relationships[key].query_class is not None: if hasattr(items, "all"): items = items.all() ret_data[key] = [] for item in items: ret_data[key].append( item.to_dict( show=list(show), _hide=list(_hide), _path=("%s.%s" % (_path, key.lower())), ) ) else: if ( self.__mapper__.relationships[key].query_class is not None or self.__mapper__.relationships[key].instrument_class is not None ): item = getattr(self, key) if item is not None: ret_data[key] = item.to_dict( show=list(show), _hide=list(_hide), _path=("%s.%s" % (_path, key.lower())), ) else: ret_data[key] = None else: ret_data[key] = getattr(self, key) for key in list(set(properties) - set(columns) - set(relationships)): if key.startswith("_"): continue if not hasattr(self.__class__, key): continue attr = getattr(self.__class__, key) if not (isinstance(attr, property) or isinstance(attr, QueryableAttribute)): continue check = "%s.%s" % (_path, key) if check in _hide or key in hidden: continue if check in show or key in default: val = getattr(self, key) if hasattr(val, "to_dict"): ret_data[key] = val.to_dict( show=list(show), _hide=list(_hide), _path=("%s.%s" % (_path, key.lower())) _path = ('%s.%s' % (path, key.lower())),) else: try: ret_data[key] = json.loads(json.dumps(val)) except: pass return ret_data