Как реализовать функцию кнопки «Мне нравится» в сообщениях в Python Flask? - PullRequest
0 голосов
/ 05 октября 2018

Так что я пытаюсь добавить, чтобы добавить функцию кнопки «Мне нравится» в мой код, которая позволяет пользователям нравится определенные сообщения.Лайки будут привязаны к зарегистрированному пользователю, и будет показано количество лайков.Реализация переднего конца не будет трудной, но у меня возникла проблема с задним концом.

Я использую этот пост здесь как руководство, которое вместо этого использует систему последователей

Это то, что у меня есть?

Я создал таблицу для лайков в 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

в моем rout.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'

Я сделал раздел комментариев, и я знаю, что отношение к лайкам будет одинаковым с комментариями, но я изо всех сил пытаюсь это реализовать.Я относительно новичок в колбе, и я пытался использовать документацию, но не нашел ничего, что могло бы мне помочь ...

Это моя последняя надежда.

Ответы [ 3 ]

0 голосов
/ 06 октября 2018
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 %}
0 голосов
/ 09 мая 2019

Приведенный выше код работает, но выходит из системы из-за ошибки «user_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 %}
0 голосов
/ 05 октября 2018

Ваша ошибка указывает на то, что экземпляр пользователя не имеет правильно определенного отношения likers.

Я подозреваю, что здесь есть несколько ошибок:

  1. Ваша таблица likers должнавнешний ключ для liker_id указывает на таблицу пользователей, а не на сообщения.
  2. Ваше отношение liked в модели User должно быть отношением с моделью Postlikers таблица как вторичная) и не быть в отношениях с самим собой (т. Е. Модель 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] > 0

  4. (не связано, но возможно неправильно) Порядок, который ваша модель User наследует от db.Model и UserMixin, имеет значение, в настоящее время ваш UserMixin используется только для методов, которые не найдены в db.Model и не будут переопределенычто угодно (может быть, это то, что вы хотите).Ссылка: Python Порядок разрешения методов (MRO)

...