⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 strategies.py

📁 SQLAlchemy. 经典的Python ORM框架。学习必看。
💻 PY
📖 第 1 页 / 共 3 页
字号:
            if result:                return result[0]            else:                return None        class EagerLoader(AbstractRelationLoader):    """Loads related objects inline with a parent query."""        def init(self):        super(EagerLoader, self).init()        self.clauses = {}        self.join_depth = self.parent_property.join_depth    def init_class_attribute(self):        # class-level eager strategy; add the PropertyLoader        # to the parent's list of "eager loaders"; this tells the Query        # that eager loaders will be used in a normal query        self.parent._eager_loaders.add(self.parent_property)                # initialize a lazy loader on the class level attribute        self.parent_property._get_strategy(LazyLoader).init_class_attribute()            def setup_query(self, context, parentclauses=None, parentmapper=None, **kwargs):        """Add a left outer join to the statement thats being constructed."""                path = context.path                # check for join_depth or basic recursion,        # if the current path was not explicitly stated as         # a desired "loaderstrategy" (i.e. via query.options())        if ("loaderstrategy", path) not in context.attributes:            if self.join_depth:                if len(path) / 2 > self.join_depth:                    return            else:                if self.mapper.base_mapper in path:                    return        if parentmapper is None:            localparent = context.mapper        else:            localparent = parentmapper                if context.eager_joins:            towrap = context.eager_joins        else:            towrap = context.from_clause                # create AliasedClauses object to build up the eager query.  this is cached after 1st creation.            try:            clauses = self.clauses[path]        except KeyError:            clauses = mapperutil.PropertyAliasedClauses(self.parent_property, self.parent_property.polymorphic_primaryjoin, self.parent_property.polymorphic_secondaryjoin, parentclauses)            self.clauses[path] = clauses        # place the "row_decorator" from the AliasedClauses into the QueryContext, where it will        # be picked up in create_row_processor() when results are fetched        context.attributes[("eager_row_processor", path)] = clauses.row_decorator                if self.secondaryjoin is not None:            context.eager_joins = sql.outerjoin(towrap, clauses.secondary, clauses.primaryjoin).outerjoin(clauses.alias, clauses.secondaryjoin)                        # TODO: check for "deferred" cols on parent/child tables here ?  this would only be            # useful if the primary/secondaryjoin are against non-PK columns on the tables (and therefore might be deferred)                        if self.order_by is False and self.secondary.default_order_by() is not None:                context.eager_order_by += clauses.secondary.default_order_by()        else:            context.eager_joins = towrap.outerjoin(clauses.alias, clauses.primaryjoin)            # ensure all the cols on the parent side are actually in the            # columns clause (i.e. are not deferred), so that aliasing applied by the Query propagates             # those columns outward.  This has the effect of "undefering" those columns.            for col in sql_util.find_columns(clauses.primaryjoin):                if localparent.mapped_table.c.contains_column(col):                    context.primary_columns.append(col)                            if self.order_by is False and clauses.alias.default_order_by() is not None:                context.eager_order_by += clauses.alias.default_order_by()        if clauses.order_by:            context.eager_order_by += util.to_list(clauses.order_by)                for value in self.select_mapper.iterate_properties:            context.exec_with_path(self.select_mapper, value.key, value.setup, context, parentclauses=clauses, parentmapper=self.select_mapper)            def _create_row_decorator(self, selectcontext, row, path):        """Create a *row decorating* function that will apply eager        aliasing to the row.                Also check that an identity key can be retrieved from the row,        else return None.        """                #print "creating row decorator for path ", "->".join([str(s) for s in path])                if ("eager_row_processor", path) in selectcontext.attributes:            decorator = selectcontext.attributes[("eager_row_processor", path)]            if decorator is None:                decorator = lambda row: row        else:            if self._should_log_debug:                self.logger.debug("Could not locate aliased clauses for key: " + str(path))            return None        try:            decorated_row = decorator(row)            # check for identity key            identity_key = self.select_mapper.identity_key_from_row(decorated_row)            # and its good            return decorator        except KeyError, k:            # no identity key - dont return a row processor, will cause a degrade to lazy            if self._should_log_debug:                self.logger.debug("could not locate identity key from row '%s'; missing column '%s'" % (repr(decorated_row), str(k)))            return None    def create_row_processor(self, selectcontext, mapper, row):        row_decorator = self._create_row_decorator(selectcontext, row, selectcontext.path)        if row_decorator is not None:            def execute(instance, row, isnew, **flags):                decorated_row = row_decorator(row)                if not self.uselist:                    if self._should_log_debug:                        self.logger.debug("eagerload scalar instance on %s" % mapperutil.attribute_str(instance, self.key))                    if isnew:                        # set a scalar object instance directly on the                        # parent object, bypassing InstrumentedAttribute                        # event handlers.                        #                        instance.__dict__[self.key] = self.select_mapper._instance(selectcontext, decorated_row, None)                    else:                        # call _instance on the row, even though the object has been created,                        # so that we further descend into properties                        self.select_mapper._instance(selectcontext, decorated_row, None)                else:                    if isnew or self.key not in instance._state.appenders:                        # appender_key can be absent from selectcontext.attributes with isnew=False                        # when self-referential eager loading is used; the same instance may be present                        # in two distinct sets of result columns                                                if self._should_log_debug:                            self.logger.debug("initialize UniqueAppender on %s" % mapperutil.attribute_str(instance, self.key))                        collection = attributes.init_collection(instance, self.key)                        appender = util.UniqueAppender(collection, 'append_without_event')                        instance._state.appenders[self.key] = appender                                        result_list = instance._state.appenders[self.key]                    if self._should_log_debug:                        self.logger.debug("eagerload list instance on %s" % mapperutil.attribute_str(instance, self.key))                    self.select_mapper._instance(selectcontext, decorated_row, result_list)            if self._should_log_debug:                self.logger.debug("Returning eager instance loader for %s" % str(self))            return (execute, execute, None)        else:            if self._should_log_debug:                self.logger.debug("eager loader %s degrading to lazy loader" % str(self))            return self.parent_property._get_strategy(LazyLoader).create_row_processor(selectcontext, mapper, row)    def __str__(self):        return str(self.parent) + "." + self.key        EagerLoader.logger = logging.class_logger(EagerLoader)class EagerLazyOption(StrategizedOption):    def __init__(self, key, lazy=True, chained=False, mapper=None):        super(EagerLazyOption, self).__init__(key, mapper)        self.lazy = lazy        self.chained = chained            def is_chained(self):        return not self.lazy and self.chained            def process_query_property(self, query, paths):        if self.lazy:            if paths[-1] in query._eager_loaders:                query._eager_loaders = query._eager_loaders.difference(util.Set([paths[-1]]))        else:            if not self.chained:                paths = [paths[-1]]            res = util.Set()            for path in paths:                if len(path) - len(query._current_path) == 2:                    res.add(path)            query._eager_loaders = query._eager_loaders.union(res)        super(EagerLazyOption, self).process_query_property(query, paths)    def get_strategy_class(self):        if self.lazy:            return LazyLoader        elif self.lazy is False:            return EagerLoader        elif self.lazy is None:            return NoLoaderEagerLazyOption.logger = logging.class_logger(EagerLazyOption)# TODO: enable FetchMode option.  currently # this class does nothing.  will require Query# to swich between using its "polymorphic" selectable# and its regular selectable in order to make decisions# (therefore might require that FetchModeOperation is performed# only as the first operation on a Query.)class FetchModeOption(PropertyOption):    def __init__(self, key, type):        super(FetchModeOption, self).__init__(key)        if type not in ('join', 'select'):            raise exceptions.ArgumentError("Fetchmode must be one of 'join' or 'select'")        self.type = type            def process_query_property(self, query, properties):        query.attributes[('fetchmode', properties[-1])] = self.type        class RowDecorateOption(PropertyOption):    def __init__(self, key, decorator=None, alias=None):        super(RowDecorateOption, self).__init__(key)        self.decorator = decorator        self.alias = alias    def process_query_property(self, query, paths):        if self.alias is not None and self.decorator is None:            (mapper, propname) = paths[-1][-2:]            prop = mapper.get_property(propname, resolve_synonyms=True)            if isinstance(self.alias, basestring):                self.alias = prop.target.alias(self.alias)            self.decorator = mapperutil.create_row_adapter(self.alias, prop.target)        query._attributes[("eager_row_processor", paths[-1])] = self.decoratorRowDecorateOption.logger = logging.class_logger(RowDecorateOption)        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -