def sort_query(self, query, sort_info): """Sort query according to jsonapi 1.0 :param Query query: sqlalchemy query to sort :param list sort_info: sort information :return Query: the sorted query """ for sort_opt in sort_info: field = sort_opt['field'] if sort_opt.get('relationship'): current_schema = self.resource.schema for obj in sort_opt['relationship'].split('.'): current_schema = get_related_schema(current_schema, obj) if not hasattr(current_schema.Meta, 'model'): raise InvalidSort("In order to sort on a relationship, meta model must be defined") relationship_model = current_schema.Meta.model query = query.join(relationship_model) relationship_model = current_schema.Meta.model model_field = get_model_field(current_schema, sort_opt['field']) query = query.order_by(getattr(getattr(relationship_model, model_field), sort_opt['order'])()) elif not hasattr(self.model, field): raise InvalidSort("{} has no attribute {}".format(self.model.__name__, field)) else: query = query.order_by(getattr(getattr(self.model, field), sort_opt['order'])()) return query
def eagerload_includes(self, query, qs): """Use eagerload feature of sqlalchemy to optimize data retrieval for include querystring parameter :param Query query: sqlalchemy queryset :param QueryStringManager qs: a querystring manager to retrieve information from url :return Query: the query with includes eagerloaded """ for include in qs.include: joinload_object = None if '.' in include: current_schema = self.resource.schema for obj in include.split('.'): try: field = get_model_field(current_schema, obj) except Exception as e: raise InvalidInclude(str(e)) if joinload_object is None: joinload_object = joinedload(field, innerjoin=True) else: joinload_object = joinload_object.joinedload( field, innerjoin=True) related_schema_cls = get_related_schema( current_schema, obj) if isinstance(related_schema_cls, SchemaABC): related_schema_cls = related_schema_cls.__class__ else: related_schema_cls = class_registry.get_class( related_schema_cls) current_schema = related_schema_cls else: try: field = get_model_field(self.resource.schema, include) except Exception as e: raise InvalidInclude(str(e)) joinload_object = joinedload(field, innerjoin=True) query = query.options(joinload_object) return query