Hello Michael,

Thank you for the speedy response!  bindparam was exactly what I was 
looking for.  While I can go through the entire application and try to make 
sure each query is accounted for/has the filter added, I think it more 
likely to catch all of them by applying the filter at the model level where 
appropriate.  With the bindparam option, all I needed to modify was the 
model, and the authentication bits - and from what I can tell, the rest now 
behaves correctly.  As you predicted, the first version I wrote ended up 
having the first organisation used baked into the entire model.

Thank you again for your support,
Damian

On Monday, 21 January 2013 16:07:15 UTC, Michael Bayer wrote:
>
>
> On Jan 21, 2013, at 8:41 AM, Damian Dimmich wrote: 
>
> > Hi 
> > 
> > I have an application that was originally written to support just one 
> organisation.  This app is now being modified to support multiple 
> organisations.  As such I am trying to update the main bits of the model to 
> always filter queries by organisation_id, a new column I have added in to 
> the relevant tables. 
> > 
> > For example, a class Users, used for authentication would have (so the 
> login/logout/reset password functions would be modified to use this): 
> > 
> > class AllUser(Base): 
> >    __tablename__ = 'users' 
> >    id = sa.Column(sa.Integer, primary_key=True) 
> >    username = sa.Column(sa.Unicode(15), nullable=False, unique=True) 
> >    organisation_id = sa.Column(sa.Integer, sa.ForeignKey('
> organisation.id')) 
> >    organisation = sa.orm.relationship('Organisation') 
> > 
> > 
> > and the 'restricted' version would just show users from the organisation 
> (all other existing parts of the application would use this class for its 
> queries) : 
> > 
> > class User(Base): 
> >    __table__ = 
> select([users_table]).where(users_table.c.organisation_id==session['organisation_id'])
>  
>
> >    id = sa.Column(sa.Integer, primary_key=True) 
> >    username = sa.Column(sa.Unicode(15), nullable=False, unique=True) 
> >    organisation_id = sa.Column(sa.Integer, sa.ForeignKey('
> organisation.id')) 
> >    organisation = sa.orm.relationship('Organisation') 
> > 
> > where session['organisation_id'] is the organisation id of the currently 
> logged in user. 
> > 
> > Is this a sensible approach?  Are there any concurrency issues I should 
> be aware of such as: would the __table__ select statement be cached/reused 
> from one request to the next? 
>
> well yeah that actually wouldn't work at all, __table__ = select()... is 
> evaluated immediately, so whatever is in "session['org_id']" at that point 
> is baked into the query. 
>
> You can make it work if you use a callable there ("callable_" with 
> bindparam() is SQLAlchemy 0.8): 
>
>         __table__ = select(...).where(table.c.org_id == bindparam(None, 
> callable_=lambda: session['organization_id'])) 
>
> but why is it important that the query here be broken up at the class 
> level ?   The only time the difference between AllUser and User has any 
> significance is when you say: 
>
>         query(AllUser)  / query(User) 
>
> why is that better than just saying: 
>
>         query(User) / query(User).filter(User.with_session_organization) 
>
> ?   (an expression like "User.with_session_organization" can be created 
> using a hybrid attribute: 
> http://docs.sqlalchemy.org/en/rel_0_8/orm/extensions/hybrid.html) 
>
> unless it's your aim to create a relationship() that refers to User.  In 
> which case you can also add that bindparam() idea to the "primaryjoin" 
> condition of relationship.  An example that uses this technique is here: 
> http://www.sqlalchemy.org/trac/wiki/UsageRecipes/GlobalFilter  though if 
> you had a callable_ inside the bindparam(), you wouldn't need the "options" 
> used in that example. 
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/USQ5xoTMwFsJ.
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