On Tue, Dec 6, 2011 at 12:38 PM, Daniel Nouri <[email protected]> wrote:
> On Mon, Dec 5, 2011 at 11:30 PM, Michael Bayer <[email protected]>
> wrote:
>> On Dec 5, 2011, at 1:39 PM, Daniel Nouri wrote:
>>> 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. :-)
>>
>> OK, well with_transformation is literally:
>>
>> def with_transformation(self, fn):
>> return fn(self)
>>
>> so there's not much controversy there. I've added it and wrote up an
>> example of how to combine this with a hybrid comparator, to produce two
>> approaches for your problem (which just makes a nice example). It looks
>> *interesting*, but I don't know how much this pattern would catch on - if
>> it's one of those patterns that can keep expanding out or not. Check it
>> out at:
>>
>> http://www.sqlalchemy.org/docs/orm/extensions/hybrid.html#building-transformers
>
> Awesome! Thanks for not only giving me a way to do this, but
> basically solve my homework too. :-)
>
> I have to admit I only understood Comparators now. And why the need
> for a 'with_transformation' on top of the Comparators. The way
> GrandparentTransformer's functionality is put together using
> 'with_transform' seems very elegant.
>
> The GrandparentTransformer in the second example that separates 'join'
> from 'filter' seems interesting and the implementation slightly
> easier, but the query part is definitely harder in a way that exposes
> maybe a lot of what's going on behind the scenes.
>
> I imagine that novice users would also be tempted to think that they
> can do "query.filter(Node.grandparent == Node(id=5))". Since the
> "join" in your example doesn't affect the way that subsequent filters
> work, I guess it's not useful for the user (doing the query) to know
> if it's a transform or a filter, right? (I don't pretend I understand
> the full scope of this, so wouldn't be surprised if this were a choice
> of explicit over implicit or some such.)
Here's a little generalization of that GrandparentTransformer that I
came up with.
class ParentalTransformer(Comparator):
def __init__(self, expression, level):
super(ParentalTransformer, self).__init__(expression)
self.level = level
def operate(self, op, other):
def transform(query):
cls = Node
for i in range(self.level-1):
cls, prev_cls = aliased(cls), cls
query = query.filter(cls.id==prev_cls.parent_id)
return query.filter(op(cls.parent, other))
return transform
This one tries to do arbitrary depths -- because in my real life
example I needed three levels really (query on grand-grandparent). It
also turned out that when using polymorphic subclasses of Node (my
tree is really different types of Nodes), I had to use "Node" instead
of "self.__clause_element__()", or else the generated query would
assume that all nodes along the way were of the same type as
"self.__clause_element__()". (I *think* this would apply to the
example in the docs too if one were to use polymorphic.)
Does this look right? :-)
--
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.