0

I am rather new to flask and sql-alchemy. I am having trouble with relationships between different models. Specifically, I am trying to print to the front-end HTML the usernames of the users that liked a specific post.

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True) 
    posts = db.relationship('Post', backref='author', lazy=True)
    posts = db.relationship('Post', backref='author', primaryjoin="User.id==Post.author_id")
    ...


    liked = db.relationship(
        'PostLike',
        foreign_keys='PostLike.user_id',
        backref='user', lazy='dynamic')


    def like_post(self, post):
        if not self.has_liked_post(post):
            like = PostLike(user_id=self.id, post_id=post.id)
            db.session.add(like)

    def unlike_post(self, post):
        if self.has_liked_post(post):
            PostLike.query.filter_by(
                user_id=self.id,
                post_id=post.id).delete()

    def has_liked_post(self, post):
        return PostLike.query.filter(
            PostLike.user_id == self.id,
            PostLike.post_id == post.id).count() > 0


class PostLike(db.Model):
    __tablename__ = 'post_like'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    post_id = db.Column(db.Integer, db.ForeignKey('post.id'))


class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    recipient_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    likes = db.relationship('PostLike', backref='post', lazy='dynamic')
    ...

In my flask application, when printing out posts, I want to be able to display the usernames of the likers of the post. I have been able to get the like function to work and display the number of likes, through:

{{ post.likes.count() }}

through jinja2 in the HTML front-end.

aj3409
  • 186
  • 2
  • 14

1 Answers1

0

Because your post_like table is just a simple pairing of two rows in different tables, you can use a secondary relationship to reach through that directly to the user object.

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    recipient_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    likes = db.relationship('User', secondary='post_like',
                            backref=db.backref('post', lazy='dynamic'))

If you wanted to add more columns to the secondary table, then you'll have to use the more-complex Association Object pattern.

Also, you shouldn't have two posts relationships, they need to be merged.

Nick K9
  • 3,885
  • 1
  • 29
  • 62
  • Thanks, it does display the usernames. However, how would I display the number of likers? `{{ post.likes.count() }}` returns this error `TypeError: count() takes exactly one argument (0 given)`. On the other hand, `{{ post.likes.count }}` returns the object `` in the HTML page. – aj3409 Jul 07 '19 at 03:08
  • 1
    You need to [do that in Jinja](https://stackoverflow.com/questions/1465249/get-lengths-of-a-list-in-a-jinja2-template#1466550). – Nick K9 Jul 07 '19 at 07:51