On 12/17/2011 12:10 PM, Michael Bayer wrote:
On Dec 17, 2011, at 11:32 AM, Kent wrote:
Hate to bother again, but I've been down this road several times and
even created a less than adequate solution but am determined to make
this area more usable:
Problem: I'd like to easily be able to specify to a query
"disable_other_eagerloads", in a manner similar to
enable_eagerloads(False), except it only affects relationships not
specifically joined/subquery loaded for that query.
I've taken to heart comments you've made more than once about avoiding
marking lazy=False in the relationship mappings. In fact, I've seen
they have a very evil side, I've tried to portrait them as potentially
evil to the engineers I work with who would more happily take the lazy
approach of eagerloading everything in the mappers so they don't have
to think about it. I've also removed the majority of them.
Still, there are relationships that, far more often than not will need
to be joinloaded, so some are still marked as lazy=False. I suspect I
may rip my hair out someday and remove every last one of them, but in
the meantime, a query option that shuts off all those you haven't
specifically mentioned in the query would be very useful.
You turn them off with the lazyload() option. Guessing you want this
generically. You'd build a function that iterates through
mapper.get_properties() for each entity in the Query, checks each
MapperProperty with isinstance(x, RelationshipProperty), checks lazy=False,
then adds it to a list. Output is a collection of lazyload() options you
send to options:
query.options(*lazyload_all_except("x", "y"))
Keep in mind this doesn't have to traverse deeply, only on the attributes that
are immediately present.
A more comprehensive way would be to subclass MapperOption and have it actually
look and see what joinedloads are already present, though that requires knowing
about the conventions that the loader options use within the query._attributes
dictionary. It also would have to be the last thing you call on options.
A feature might look like that. Or it would put in some other symbol into
query._attributes that everyone needs to check. compare to
http://www.sqlalchemy.org/trac/ticket/1418 .
Yeah, the approach that iterates over the properties you don't pass is
the one I wrote a bit back, even called it .lazyload_except(). But
that's what I referred to as the "
less than adequate solution". I want it to be much easier to use so I'm not
requiring the user to specify the joinedloads twice (once for the joinedload and
once for the .lazyload_except(). So i'm after your second alternative.
_get_context_strategy() looks promising to me. By default, if a relationship
(or column, in the case of ticket #1418) isn't specified in the
context.attributes as a 'loaderstrategy', then self. strategy is returned.
def _get_context_strategy(self, context, path):
cls = context.attributes.get(('loaderstrategy',
_reduce_path(path)), None)
if cls:
try:
return self.__all_strategies[cls]
except KeyError:
return self.__init_strategy(cls)
else:
return self.strategy
I can reference the query from the context and then change the default behavior
to return a self.__init_strategy(LazyLoader) if the query has been told to lazy
load all others?
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en.