Sergey V. wrote:
>> Some assumptions:
>> 1. "SA-mapped object" means the user object in the example
>> 2. "property name" means "addresses" in the example
>> 3. The function shouldn't assume that you want an Address object
>> 4. The ID attribute is known ahead of time (e.g. its always "id"). If
>> not, your function will need another parameter.
>> 5. The function needs to work on many-to-many relationships in addition
>> to one-to-many.
>>
>> Then this should work:
>> def get_related_by_id(obj, property_name, id):
>>     relation = getattr(obj.__class__, property_name) # in example:
>> User.addresses
>>     related_class = relation.property.argument # in example: Address
>>     return Session.query(related_class).filter(relation.any(id=id)).first()
>>
>> example usage:
>> address_exists = get_related_by_id(user, "addresses", 1234) is not None
>>     
>
> Cool, it almost solves my problem!
>
> However, it doesn't check if a User have a given Address, it just
> checks if an Address exists in general. It would be easy to add
> another filter() by User.id, but that wouldn't work for many-to-many
> relations.
>
> My hope was to somehow get a Query object from a relation property
> with everything already set up (imagining that a relation somewhere
> stores the query it itself uses) and then just attach another filter()
> to it.
>
> Imaginary code:
>
> relation = getattr(obj.__class__, property_name)
> q = relation.get_query(...)
> result = q.filter(id = address_id).first()
>
> This approach works in Django's ORM, so it definitely should be doable
> in SA :)
The "relation.any(id=id)" part will produce an EXISTS clause relating
the address to the given user. However, now that I think about it, I
believe it will only work if you are querying users, not addresses (due
to the way that any() correlates its EXISTS clause to the outer query).

Luckily, SQLAlchemy provides another query method, with_parent(), that
should work, and is a bit cleaner than my first approach:
q = session.query(Address)
q = q.with_parent(user, "addresses")
q = q.filter_by(id=address_id)
result = q.first()

or, as a generic function:
def get_related_by_id(obj, property_name, id):
    relation = getattr(obj.__class__, property_name)
    related_class = relation.property.argument
    q = session.query(related_class)
    q = q.with_parent(obj, property_name)
    q = q.filter_by(id=id)
    result = q.first()

Finally, SQLAlchemy has a (deprecated, unfortunately) Query classmethod
that makes it cleaner still:
def get_related_by_id(obj, property_name, id):
    q = Query.query_from_parent(obj, property_name)
    q = q.filter_by(id=id)
    return q.first()

-Conor


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to