On Mon, Dec 5, 2011 at 6:42 PM, Michael Bayer <[email protected]> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>
> On Dec 5, 2011, at 11:58 AM, Daniel Nouri wrote:
>
>> Say I have a class that derives from a Node class that has a 'parent'
>> relationship (using 'parent_id' and 'id' fields):
>>
>>    from sqlalchemy.ext.hybrid import hybrid_property
>>
>>    class MyClass(Node):
>>        @hybrid_property
>>        def grandparent(self):
>>            return self.parent.parent
>>
>>        @grandparent.expression
>>        def grandparent(cls):
>>            pass # hmm?
>>
>> How would I go about the implementing the grandparent hybrid
>> expression?  What I have is a boolean clause list with two comparisons
>> of 'parent_id' and 'id' using aliases (not included in the example).
>> I was hoping I could return that but it's not what it expects.
>>
>> Thanks for your help.
>
> yeah so this is where @hybrid can....not really do the whole thing.    
> Basically when you use a hybrid on a relationship, the @expression version 
> returns whatever it is that's most useful, given the context that you'd be 
> using it within.  It of course cannot imply the automatic generation of 
> join() or anything like that, which is a manual thing...unless you had 
> @expression return a function that would process a given Query, which is 
> pretty nasty and not really helpful.
>
> So in this case, I'm not even sure @expression can return a concept that is 
> meaningfully the "grandparent" - usually the best it can do is return 
> "cls.parent", but in this case that directly contradicts that it's called 
> "grandparent".
>
> that would look like:
>
> q = session.query(MyClass).\
>          join(parent_alias, MyClass.grandparent).\
>          filter(parent_alias.grandparent == some_object)
>
> which is nasty because .grandparent is the same as .parent, so don't do that.
>
>  If it returned an aliased(cls).parent, then that alias object would need to 
> be memoized so that you can refer to it multiple times in the query (which is 
> possible).  That would make the usage something like:
>
> parent _alias = aliased(MyClass)
>
> q = session.query(MyClass).\
>        join(parent_alias, MyClass.parent).\
>        join(MyClass.grandparent, parent_alias.parent).\
>        filter(MyClass.grandparent == some_node)
>
> which also makes little sense, so....probably don't do that either :).
>
> another awful thought I had, return a query option that runs it through 
> join(..., aliased=True):
>
> q = session.query(MyClass).\
>         options(MyClass.grandparent).\
>         filter_by(id=id_of_my_grandparent)
>
> I'd need to enhance options() a bit, or provide some other method to Query 
> like query.with_transformation(fn) that runs the query through a given 
> callable.
>
> the query above is completely opaque and pretty much can do just the one 
> thing it's been set up to do, not very useful :)
>
> or if one were to really go nuts with that approach and produce a comparator 
> with an __eq__() method, maybe even:
>
> session.query(MyClass).with_transformation(MyClass.grandparent==some_parent)
>
> but I consider that to be kind of a novelty.   Or maybe not, 
> with_transformation() might be a handy method to add in any case.
>
> so yeah @expression.grandparent is not really very useful given the explicit 
> nature of the Query object, unless you seek to build tricks that build up the 
> Query behind the scenes.

Thanks for your explanation.  I haven't used hybrid a lot yet and this
helped me understand what it does and what not.

Your last example that uses a 'with_transformation', i.e. a protocol
that I guess would amount to allowing to run the query through an
arbitrary function, is quite nice to read, and I'd definitely be a
user.  Then again, there's nice enough alternatives for what I'm
trying to do, so I'll be fine without.  :-)


-- 
http://danielnouri.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.

Reply via email to