【问题标题】:How do I implement a like button function to posts in Python Flask?如何在 Python Flask 中为帖子实现点赞按钮功能?
【发布时间】:2019-03-10 23:11:54
【问题描述】:

所以我试图在我的代码中添加一个点赞按钮功能,允许用户喜欢特定的帖子。点赞将链接到登录用户,并显示点赞数。实现前端并不难,但我遇到了后端问题。

我是using this post here as a guide which does a follower system instead

这是我目前所拥有的?

我在 models.py 中为喜欢创建了一个表:

likers = db.Table('likers',
    db.Column('liker_id', db.Integer, db.ForeignKey('post.id')),
    db.Column('liked_id', db.Integer, db.ForeignKey('post.id'))
)

在我的用户类的 Models.py 中:

class User(db.Model, UserMixin):
#Code 
liked = db.relationship(
    'User', secondary=likers,
    primaryjoin=(likers.c.liker_id == id),
    secondaryjoin=(likers.c.liked_id == id),
    backref = db.backref('likers', lazy='dynamic'), lazy='dynamic')
def like(self, post):
    if not self.is_liking(post):
        self.liked.append(post)

def unlike(self, post):
    if self.is_liking(post):
        self.liked.remove(post)

def is_liking(self, post):
    return self.liked.filter(
        likers.c.liked_id == post.id).count() > 0

在我的用户蓝图的 routes.py 中,我有:

@users.route("/like/<int:post_id>")
@login_required
def like(post_id):
 post = Post.query.get_or_404(post_id)
 current_user.like(post)
 db.session.commit()
 flash('Post has been liked')
 return redirect(url_for('posts.post', post_id=post.id))

@users.route("/unlike/<int:post_id>")
@login_required
def unlike(post_id):
 post = Post.query.get_or_404(post_id)
 current_user.unlike(post)
 db.session.commit()
 flash('Post has been unliked')
 return redirect(url_for('posts.post', post_id=post.id))    

我做错了什么?我不断收到错误,例如:

builtins.KeyError
KeyError: 'likers'

我已经做了一个评论部分,我知道喜欢的关系将类似于 cmets,但我正在努力实现它。我对烧瓶比较陌生,我尝试过使用文档,但没有找到任何可以帮助我的东西......

这是我最后的希望。

【问题讨论】:

  • 在您的“likers”表中,liker_id 的外键应引用 user.id,而不是 post.id。帖子不喜欢帖子,用户喜欢帖子。
  • @onosendi 我已经这样做了,但我仍然遇到问题

标签: python flask sqlalchemy flask-sqlalchemy


【解决方案1】:
class User(UserMixin, db.Model):
    # Code
    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'))


@app.route('/like/<int:post_id>/<action>')
@login_required
def like_action(post_id, action):
    post = Post.query.filter_by(id=post_id).first_or_404()
    if action == 'like':
        current_user.like_post(post)
        db.session.commit()
    if action == 'unlike':
        current_user.unlike_post(post)
        db.session.commit()
    return redirect(request.referrer)

然后,当您列出您的帖子时,设置您的锚点如下:

{% for post in posts %}
  {% if current_user.has_liked_post(post) %}
    <a href="{{ url_for('like_action', post_id=post.id, action='unlike') }}">Unlike</a>
  {% else %}
    <a href="{{ url_for('like_action', post_id=post.id, action='like') }}">Like</a>
  {% endif %}
{% endfor %}

假设您的 Post 模型如下所示:

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.Text)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    recipient_id = db.Column(db.Integer, db.ForeignKey('user.id'))

    likes = db.relationship('PostLike', backref='post', lazy='dynamic')

你会使用:

p = Post.query.filter_by(id=1).first()
p.likes.count()

或者,您可以在 .html 文件中使用它:

{% for post in posts %}
  {% if current_user.has_liked_post(post) %}
    <a href="{{ url_for('like_action', post_id=post.id, action='unlike') }}">Unlike</a>
  {% else %}
    <a href="{{ url_for('like_action', post_id=post.id, action='like') }}">Like</a>
  {% endif %}
  {{ post.likes.count() }} likes
{% endfor %}

【讨论】:

  • 天哪,谢谢你的作品
  • 我将如何显示喜欢的数量
  • 我编辑了我的答案,这样你就可以返回每个帖子的点赞数。
  • 非常感谢你,我已经被困在这里大约 2 天了,你毫不费力地俯冲下来,为我节省了很多时间。感谢您的帮助
  • 这是很棒的东西。我假设这应该是一个ajax调用。也许有人可以添加/发布该功能。
【解决方案2】:

您的错误表明用户实例没有正确定义likers 关系。

我怀疑这里有几个错误:

  1. 您的likers 表应该具有指向用户表的liker_id 的外键,而不是帖子。
  2. 您在User 模型中的liked 关系应该是与Post 模型的关系(以likers 表为辅助),而不是与自身的关系(即User 模型) . 为你的关系试试这个:

    liked = db.relationship(
    'Post', secondary="likers",
    primaryjoin="likers.liker_id == users.id",
    secondaryjoin="likers.liked_id == posts.id",
    backref=db.backref('likers', lazy='dynamic'), lazy='dynamic')
    
  3. 您的is_liking() 方法似乎很奇怪。我会把它写成:

    (如果不希望每个用户有很多喜欢的帖子)return post in self.liked

    (如果期望每个用户有很多喜欢的帖子)return db.session.execute("SELECT COUNT(*) FROM likers WHERE liked_id = :post_id AND liker_id = :user_id", {'user_id': self.id, 'post_id': post.id}).fetchone()[0] &gt; 0

  4. (不相关但可能不正确)您的用户模型从db.ModelUserMixin 继承的顺序很重要,目前您的 UserMixin 仅用于在 db.Model 中找不到的方法并且不会覆盖任何东西(也许这就是你想要的)。参考:Python 的Method Resolution Order (MRO)

【讨论】:

  • 我知道有这个问题builtins.AttributeError AttributeError: 'Table' object has no attribute 'liker_id'
【解决方案3】:

以上代码有效,但由于 "current_user" 导致用户制造商错误注销。所以我们的html文件一定是这样的

{% for post in posts %}
    {% if current_user.is_authenticated %}
        {% if current_user.has_liked_post(post) %}
            <a href="{{ url_for('like_action', post_id=post.id, action='unlike') }}">Unlike</a>
        {% else %}
            <a href="{{ url_for('like_action', post_id=post.id, action='like') }}">Like</a>
        {% endif %}
        {{ post.likes.count() }} likes
    {% else %}
        {{ post.likes.count() }} likes
    {% endif %}{% endfor %}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多