コード例 #1
0
ファイル: interface.py プロジェクト: yuyou/Flask-AppBuilder
    def apply_order_by(
        self,
        query: Query,
        order_column: str,
        order_direction: str,
        aliases_mapping: Dict[str, AliasedClass] = None,
    ) -> Query:
        if order_column != "":
            # if Model has custom decorator **renders('<COL_NAME>')**
            # this decorator will add a property to the method named *_col_name*
            if hasattr(self.obj, order_column):
                if hasattr(getattr(self.obj, order_column), "_col_name"):
                    order_column = getattr(self._get_attr(order_column), "_col_name")
            _order_column = self._get_attr(order_column) or order_column

            if is_column_dotted(order_column):
                root_relation = get_column_root_relation(order_column)
                # On MVC we still allow for joins to happen here
                if not self.is_model_already_joined(
                    query, self.get_related_model(root_relation)
                ):
                    query = self._query_join_relation(
                        query, root_relation, aliases_mapping=aliases_mapping
                    )
                column_leaf = get_column_leaf(order_column)
                _alias = self.get_alias_mapping(root_relation, aliases_mapping)
                _order_column = getattr(_alias, column_leaf)
            if order_direction == "asc":
                query = query.order_by(asc(_order_column))
            else:
                query = query.order_by(desc(_order_column))
        return query
コード例 #2
0
ファイル: interface.py プロジェクト: yuyou/Flask-AppBuilder
 def exists_col_to_many(self, select_columns: List[str]) -> bool:
     for column in select_columns:
         if is_column_dotted(column):
             root_relation = get_column_root_relation(column)
             if self.is_relation_many_to_many(
                 root_relation
             ) or self.is_relation_one_to_many(root_relation):
                 return True
     return False
コード例 #3
0
ファイル: interface.py プロジェクト: yuyou/Flask-AppBuilder
    def apply_inner_select_joins(
        self,
        query: Query,
        select_columns: List[str] = None,
        aliases_mapping: Dict[str, AliasedClass] = None,
    ) -> Query:
        """
        Add select load options to query. The goal
        is to only SQL select what is requested and join all the necessary
        models when dotted notation is used. Inner implies non dotted columns
        and many to one and one to one

        :param query:
        :param select_columns:
        :return:
        """
        if not select_columns:
            return query
        joined_models = list()
        for column in select_columns:
            if is_column_dotted(column):
                root_relation = get_column_root_relation(column)
                leaf_column = get_column_leaf(column)
                if self.is_relation_many_to_one(
                    root_relation
                ) or self.is_relation_one_to_one(root_relation):
                    if root_relation not in joined_models:
                        query = self._query_join_relation(
                            query, root_relation, aliases_mapping=aliases_mapping
                        )
                        query = query.add_entity(
                            self.get_alias_mapping(root_relation, aliases_mapping)
                        )
                        # Add relation FK to avoid N+1 performance issue
                        query = self._apply_relation_fks_select_options(
                            query, root_relation
                        )
                        joined_models.append(root_relation)

                    related_model_ = self.get_alias_mapping(
                        root_relation, aliases_mapping
                    )
                    relation = getattr(self.obj, root_relation)
                    # The Zen of eager loading :(
                    # https://docs.sqlalchemy.org/en/13/orm/loading_relationships.html
                    query = query.options(
                        contains_eager(relation.of_type(related_model_)).load_only(
                            leaf_column
                        )
                    )
                    query = query.options(Load(related_model_).load_only(leaf_column))
            else:
                query = self._apply_normal_col_select_option(query, column)
        return query
コード例 #4
0
ファイル: interface.py プロジェクト: yuyou/Flask-AppBuilder
    def get_inner_filters(self, filters: Optional[Filters]) -> Filters:
        """
        Inner filters are non dotted columns and
        one to many or one to one relations

        :param filters: All filters
        :return: New filtered filters to apply to an inner query
        """
        inner_filters = Filters(self.filter_converter_class, self)
        _filters = []
        if filters:
            for flt, value in zip(filters.filters, filters.values):
                if not is_column_dotted(flt.column_name):
                    _filters.append((flt.column_name, flt.__class__, value))
                elif self.is_relation_many_to_one(
                    flt.column_name
                ) or self.is_relation_one_to_one(flt.column_name):
                    _filters.append((flt.column_name, flt.__class__, value))
            inner_filters.add_filter_list(_filters)
        return inner_filters
コード例 #5
0
ファイル: interface.py プロジェクト: yuyou/Flask-AppBuilder
 def apply_outer_select_joins(
     self, query: Query, select_columns: List[str] = None
 ) -> Query:
     if not select_columns:
         return query
     for column in select_columns:
         if is_column_dotted(column):
             root_relation = get_column_root_relation(column)
             leaf_column = get_column_leaf(column)
             if self.is_relation_many_to_many(
                 root_relation
             ) or self.is_relation_one_to_many(root_relation):
                 query = query.options(
                     Load(self.obj).joinedload(root_relation).load_only(leaf_column)
                 )
             else:
                 related_model = self.get_related_model(root_relation)
                 query = query.options(Load(related_model).load_only(leaf_column))
         else:
             query = self._apply_normal_col_select_option(query, column)
     return query