Reputation: 15
I have ben trying to figure out how to run queries based on the foreign key of a SQLAlchemy model for a while and I've tried checking the documentation and looking here on stackoverflow but I can't find anything that addresses this problem I'm having. I have 2 SQLAlchemy models: User and Account defined as below:
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
fName = db.Column(db.String(255))
accounts = db.relationship("Account")
class Account(db.Model):
__tablename__ = 'account'
id = db.Column(db.Integer, primary_key=True)
account_number = db.Column(db.Integer, unique=True, nullable=False)
lName = db.Column(db.String(255), nullable=False)
client_id = db.Column(db.ForeignKey("user.id"))
What I want to do is query all of the accounts in the Account model and for each one, if it has a corresponding value in in the User model column that the client_id foreign key references, then add the value of fName from the User model in the final result. So it will look something like this:
{
"accounts": [
{
"fName": "Abbie",
"id": 1,
"account_number": 1234,
"lName": "Mills"
},
{
"fName": "Katrina",
"id": 2,
"account_number": 3848,
"lName": "Crane"
},
{
"fName": "Sheldon",
"id": 3,
"account_number": 384,
"lName": "Cooper"
},
{
"fName": "Chandler",
"id": 4,
"account_number": 1288,
"lName": "Bing"
},
{
"id": 5,
"account_number": 1283,
"lName": "Smith"
},
{
"id": 6,
"account_number": 3847,
"lName": "Gary"
},
{
"id": 7,
"account_number": 2038,
"lName": "Ryan"
}
]
}
I know this is the query I want:
class AccountList(Resource):
@account_ns.doc('get account data')
def get(self):
query = account_schema.dump(Account.query.all())
accountDict = {}
accountDict['accounts'] = []
for item in query:
itemDict = {}
itemDict = item
linkQuery = user_schema.dump(db.session.query(User.fName).filter(User.id == Account.client_id).first())
# print(linkQuery)
itemDict.update(linkQuery)
accountDict['accounts'].append(itemDict)
print(accountDict)
return accountDict, 200
but everytime the query db.session.query(User.fName).filter(User.id == Account.client_id).first() is run, the id of User doesn't seem to be incrementing and always prints the same value everytime, even for account objects that don't have a client_id. the result turns out to be this:
{
"accounts": [
{
"customer_id": 1,
"id": 1,
"lName": "Mills",
"account_number": 1234,
"fName": "Abbie"
},
{
"customer_id": null,
"id": 2,
"lName": "Smith",
"account_number": 1283,
"fName": "Abbie"
},
{
"customer_id": null,
"id": 3,
"lName": "Gary",
"account_number": 484,
"fName": "Abbie"
},
{
"customer_id": 2,
"id": 4,
"lName": "Crane",
"account_number": 3848,
"fName": "Abbie"
},
{
"customer_id": 3,
"id": 5,
"lName": "Cooper",
"account_number": 384,
"fName": "Abbie"
},
{
"customer_id": null,
"id": 6,
"lName": "Ryan",
"account_number": 223,
"fName": "Abbie"
},
{
"customer_id": 1,
"id": 7,
"lName": "Mills",
"account_number": 48494,
"fName": "Abbie"
},
{
"customer_id": 4,
"id": 9,
"lName": "Bing",
"account_number": 1288,
"fName": "Abbie"
}
]
}
which is not what I want. Is there anything I'm doing wrong here or someway I can tweak my query? The only other way I've thought of doing is creating another column in Account that has the same values as client_id but is not set as the foreign key so that I can actually reference the value for the row in that column.
I've been stuck on this for a while so any help will be greatly appreciated. Thank you!
Upvotes: 1
Views: 3848
Reputation: 334
Sqlalchemy supports backref in model. When applying relationship you can also use pass backref parameter, it will help you to access user object directly from account object.
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True)
fName = db.Column(db.String(255))
accounts = db.relationship("Account", backref="user")
class Account(db.Model):
__tablename__ = 'account'
id = db.Column(db.Integer, primary_key=True)
account_number = db.Column(db.Integer, unique=True, nullable=False)
lName = db.Column(db.String(255), nullable=False)
client_id = db.Column(db.ForeignKey("user.id"))
class AccountList(Resource):
@account_ns.doc('get account data')
def get(self):
query = Account.query.all()
account_list = []
for item in query:
account_dict = item.__dict__
if item.client_id:
accout_dict["fName"] = item.user.fName
account_list.append(account_dict)
return account_list, 200
Upvotes: 2