简体   繁体   中英

SQLAlchemy - Accessing Attribute from Bi-Directional Association Proxy

In Flask-SQLAlchemy, I have three models defined as follows:

class Account(db.Model):                                  
    __tablename__ = 'accounts'                            
    id = db.Column(db.Integer, primary_key=True)          
    name = db.Column(db.String(64))                                      
    users = association_proxy('user_accounts', 'user') 

class User(db.Model):                              
    __tablename__ = 'users'                                   
    id = db.Column(db.Integer, primary_key=True)              
    username = db.Column(db.String(64))                                             
    accounts = association_proxy('user_accounts', 'account')  

class Permission(db.Model):                                            
    __tablename__ = 'permissions'                                      
    account_id = db.Column(db.Integer, db.ForeignKey('accounts.id'), primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'),  primary_key=True)
    role = db.Column(db.Integer)                                                                                                    
    account = db.relationship("Account", backref=backref('user_accounts
    user = db.relationship("User", backref=backref('user_accounts')) 

These are used to express a many-to-many relationship between the Account and User classes, controlled by a Permission .

Currently, I can do the following:

# create initial records
a = Account()
u = User()
p = Permission()
p.account = a
p.user = u
db.session.add_all([a, u, p])
db.session.commit()
# get the list of accounts associated with a user
u.accounts
[<Account 1>]
# get the list of users associated with an account (same as above, just reverse)
a.users
[<User 1>]

However, I'm unable to get the exact role that a user has with a specific account.

Basically, I want to be able to do this:

a.users[0].role

... to be able to find out what role this user has on the specific account a . If the same line were run against a different account, called a2 , I would expect to obtain a different role (whatever role the user it's called upon has for account a2 instead of a1 ).

Is this even possible via a relationship? Or, instead, should I just loop through the Permissions to find what role the user has each time they try to access an account because this is an anti-pattern for database relationships?

A couple of options, some outlined in this post .

One is you can directly query the association object table;

permissions = Permission.query.filter_by(user_id == user_id).filter_by(account_id == account_id).one()

Or, if you already have access to the a User instance, you could find the account you're after from the users object and access the role;

account = next((aco for aco in user.accounts if aco.id == account_id), None)
if account:
    role = account.role

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM