Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sqlalchemy query from SQL with multiple where conditions

Tags:

sql

sqlalchemy

I have three tables which are defined as:

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer(10), primary_key=True)
    firstname = Column(String(64))
    surname = Column(String(64))

class SWMS(Base):
    __tablename__ = 'swms'
    id = Column(Integer(10), primary_key=True)
    owner_id = Column(Integer(10), ForeignKey('users.id', ondelete='CASCADE'))
    filename = Column(String(255))

    swmowner = relationship('User', backref=backref('users'))

class SWM_perms(Base):
    __tablename__ = 'swm_perms'
    id = Column(Integer(10), primary_key=True)
    swm_id = Column(Integer(10), ForeignKey('swms.id', ondelete='CASCADE'))
    user_id = Column(Integer(10), ForeignKey('users.id', ondelete='CASCADE'))

    swm = relationship('SWMS', backref=backref('swms'))
    swmuser = relationship('User', backref=backref('swmusers'))

Essentially, the SWMS table is a table of document info where the owner_id defines the user who created the document. SWM_perms is a table that has a mapping of document id to user id - to define which users are allowed to see the document.

To produce a table of all documents which are either 1) owned by the user or 2) are viewable by the user, in SQL I would do:

select owner_id, users.firstname, users.surname, filename
from swms, swm_perms, users
where users.id=swms.owner_id and 
  ((swms.id=swm_perms.swm_id and swm_perms.user_id = 27) or (owner_id = 27));

How would you define this query in sqlalchemy? I am familiar with the or_() function but the variants I am trying do not generate the correct objects.

like image 992
timbo Avatar asked Apr 05 '12 00:04

timbo


2 Answers

cond1 = and_(SWMS.id==SWM_perms.swm_id,SWM_perms.user_id==27)
swms = DBSession.query(User,SWMS).filter(or_(cond1,SWMS.owner_id==27)).\
                                  filter(User.id==SWMS.owner_id).all()

and then you can do a list comprehension to pull the fields you want:

details = [(u.firstname, s.filename, s.blob_key, s.last_modified) for u,s in swms]
like image 97
timbo Avatar answered Nov 14 '22 21:11

timbo


Also worth noting you can use the '&' operator, in place of 'and_', in the body of the query. See the example (second code block) they give here:

http://docs.sqlalchemy.org/en/rel_1_0/core/sqlelement.html#sqlalchemy.sql.expression.and_

like image 32
heisenBug Avatar answered Nov 14 '22 23:11

heisenBug