[sqlalchemy] Re: Check if an item exists in a relation

2009-10-29 Thread Conor

Sergey V. wrote:
 Hi all,

 I must be missing something obvious here...

 Let's suppose I have the following class:

 class User(Base):
 # 
 addresses = relation(Address, backref=user)

 and I have a number which may be an ID of an Address object. How do I
 check if the number is an ID of one of Addresses of a given User?

 I could do that just iterating over the addresses:

 for address in user.addresses:
  if address.id == ID:
 print TADA!

 ... but this doesn't seem like a good solution. There must be a way to
 make SQLAlchemy to return the value.

 (to make it a bit more interesting - the code needs to be generic,
 i.e. the function just gets some SA-mapped object and property name,
 so I can't just build a query manually like this -

 addr = session.query(Address).filter(id=address_id).filter(user_id =
 user.id).one()

 - because I don't know what the join fields are (and if possible I'd
 like this to work with many-to-many relations too)
 )

 Thanks!
   
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

-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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Check if an item exists in a relation

2009-10-29 Thread Sergey V.

 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 :)
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Check if an item exists in a relation

2009-10-29 Thread Sergey V.

Ahh... I missed the relation.any() part of your example - with it the
code should behave exactly as I need. I think. I need to give it a
try.

Thanks!

On Oct 30, 9:53 am, Sergey V. sergey.volob...@gmail.com 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 :)
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---



[sqlalchemy] Re: Check if an item exists in a relation

2009-10-29 Thread Conor

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
-~--~~~~--~~--~--~---