On 3/23/07, Michael Bayer <[EMAIL PROTECTED]> wrote:
> OK, this is actually something people have asked for a lot. in the
> beginning, recently, etc. also for different reasons...i.e.
> convenience, or performance, etc. So, first off let me start by
> illustrating how this use case is done right now. Assuming your
> Address mapper has a backref "user" to the User mapper, its just:
>
> for address in session.query(Address).filter_by(user=someuser).filter
> (address_table.c.postcode == 5000):
> print address.street
Once again, I discover a "better way" to do something I did the hard way.
> But, the join conditions and bind params which
> have been calculated by "LazyLoader" are just sitting there, they can
> be currently pulled out with a little non-API attribute access but
> Ive no problem with adding some API-level accessors to get at the
> Query object calculated for a particular property (i.e. what you are
> using in your patch internally).
Yes, please do, that'd probably solve the problem nicely (see below
how I see things).
> now lets look at the way your patch does it.
>
> addresses = user.addresses.filter(address_table.c.postcode == 5000)
> seems easy. right ? remember that "user" is now in the session.
> anyone else that queries for "user" will get that same User
> instance. but the rest of the app is going to assume normal
> relationship semantics on that collection....which means:
How I envisioned things, this wouldn't be a problem, because
user.addresses.filter(xxx) would return a new, independant list, which
doesn't affect user.addresses, and is not affected if user.addresses
has already been accessed or not. This is not what my patch does, I
know. Sorry for not explaining this in my first mail.
> print someaddress in user.addresses # <-- FAIL - the address is not
> present
> user.addresses.remove(someaddress) # <-- ERROR - the address is not
> present
>
> user.addresses.insert(5, someotheraddress) # <-- FAIL - the list is
> incomplete, ordering will be incorrect
This is only a matter of getattr and __contains__ triggering init,
right? (At least if we exclude the other problems pointed above).
> session.flush() # <-- FAIL - we have to figure out what items were
> added/removed/unchanged from the collection...but the data's
> incomplete !
I don't master SQLAlchemy internals but I don't see how that is
different from when the collection is complete?
> so as long as we can agree on the "its a read-only thing" aspect of
> this, we're good to go. otherwise you have to define for me how all
> those mutating operations are going to work (and even then, its
> additional core complexity im not sure if i can add to my support-load).
I'm fine with the readonly aspect of it. What I don't like is the fact
you have to create a readonly relation (lazyloader/whatever/...) in
advance (ie in your mapper), which is IMHO just a dupe of the normal
relation and pollutes the mapper. You'd end up with mappers like this:
mapper(SomeClass, table, properties={
'addresses':relation(Address)
'addresses2':lazyloader(Address)
})
which is pretty much as ugly as you can get.
On the other hand, I think that combined with a quick way to have
predefined filters it might be a nice addition anyway:
mapper(SomeClass, table, properties={
'addresses': relation(Address)
'local_addresses': lazyloader(Address,
filter=address.c.postcode==5000)
})
But it does in no case replace the "dynamic" "non-polluting" use-case
I'd like to have. What I had in mind is to reuse normal relations to
get a query. It feels much more natural and cleaner to me. And I think
the best compromise would be something along the lines of:
user.addresses: # use standard relation => read/write
user.addresses.filter(XXX): # returns a query => read only
the code would probably be cleaner if we did something more explicit like:
user.addresses.query # returns the query object that you can filter, etc...
though, as a user, I'd prefer the first solution.
Wouldn't that be possible? I think it should be. You only need to keep
the deferred approach of the InstrumentedList that I demonstrated in
my patch, so that the whole list is not fetched before we get the
query object, which would ruin the whole idea. Of course it was only a
proof-of-concept patch, but I think it should be fixable.
--
Gaƫtan de Menten
http://openhex.org
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---