Referencing values using foreign key on flask sql-alchemy

Question:

I have models like this:

class User(db.Model):
    _tablename='user'
    id=db.Column(db.Integer, primary_key=True)
    name=db.Column(db.String)
    email=db.Column(db.String)

class Post(db.Model):
    _tablename='post'
    id=db.Column(db.Integer, primary_key=True)
    title=db.Column(db.String)
    user=db.Column(db.Integer, db.ForeignKey('user.id'))

I would like to display the list of all posts on a web page, with something like this in html:

{% for entry in entries %}
    <tr>
       <td> {{ entry.id }} </td>
       <td> {{ entry.title }} </td>
       <td> {{ entry.user_name }} </td>
       <td> {{ entry.user_email }} </td>
{% endfor %}

However, I don’t know how to access the user and email from the user table, using the user.id foreign key. I tried

posts = Post.query.all()
for post in posts:
    post.user_name = User.query.filter_by(id=post.id).first()
return render_template('post.html', entries=posts)

But then instead of returning just the name and email, like the title from post, it is returning something like (u’User A’,) and (u’[email protected]’,).

Asked By: Wohoo Summer

||

Answers:

You are almolst there but this code below does not actually return the username. It returns the entire user object:

User.query.filter_by(id=post.id).first() # Does Not return user_name but returns the user object

So I would call it something like:

userobj = User.query.filter_by(id=post.id).first()

Then you can retrieve the username,email as:

if userobj is not None: # Make sure user exists
    username = userobj.name
    email = userobj.email

As a shortcut, you can also do:

username = User.query.filter_by(id=post.id).first().name
email = User.query.filter_by(id=post.id).first().email
Answered By: codegeek

First of all the solution is to query using the related fields.
You can get the user details using the below query:
Let us assume that the id in the user model is 1 and user in post model value is 1 i.e(id=1, user=1).

Link post model with user model
You will have link them with the related fields i.e
(User model has id and Post model has user as a foreign key)

import Post #import post model

user = User.query.filter(User.id==Post.user).first()

The below will give first post in post model created by the user

import User #import user model

post = Post.query.filter(Post.user==User.id).first()

post.id
post.title
user.name
user.email

You can also query to get all posts like below

posts = Post.query.filter(Post.user==User.id).all()
Answered By: gokulnath ck

Other answers ask you to create a second query to get the user name & email, but this is actually not necessary if you add the following to your User class definition:

posts=db.relationship('Post', backref='post_owner',lazy=True)

Your full User class definition will then be:

class User(db.Model):
    _tablename='user'
    id=db.Column(db.Integer, primary_key=True)
    name=db.Column(db.String)
    email=db.Column(db.String)
    posts=db.relationship('Post', backref='post_owner', lazy=True)

Your html can then take advantage of the relationship by referencing the ‘backref’ name:

{% for entry in entries %}
    <tr>
       <td> {{ entry.id }} </td>
       <td> {{ entry.title }} </td>
       <td> {{ entry.post_owner.name }} </td>
       <td> {{ entry.post_owner.email }} </td>

{% endfor %}

This saves you from writing additional queries and cluttering your code with additional ‘if’ statements.

Answered By: Daniel