iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Modern Web

Flask系列 第 27

Day 27 實作 user_bp (5)

前言

今天會完成 user_bp,也就是要完成看貼文跟留言的部分。

/posts

首先來看看可以看到全部人貼文的 /posts,他非常簡單,所以就不分別了,直接把 HTML 和路徑都放出來。他沒有資料庫的部分,因為我們會直接用之前的 get_posts

posts.html

{% extends "base.html" %}

{% block title %}Posts{% endblock %}

{% block content %}
<div>
    {% for post in posts %}
    <div>
        {{ post['author_id'] }}
        <a href="/post/{{ post['id'] }}">{{ post['title'] }}</a>
        {{ post['description'] }}
        {{ post['time'] }}
    </div>
    {% endfor %}
</div>
{% endblock %}

views.py


@user_bp.route("/posts", methods=["GET"])
@login_required
def all_posts_page():
    posts = get_posts()
    return render_template("posts.html", posts=posts)

基本上它的 HTML 跟 dashboard 是一樣的,只是刪掉了編輯和刪除的連結,也移掉了篩選器的表單。

路徑的部分就更簡單了,就如同剛剛所說的用 get_posts,然後不帶任何篩選器直接抓全部,再丟到 HTML 處理,而處理方式就跟昨天 dashboard 一模一樣。

/@username/posts

接下來我們先看看使用者底下的貼文,基本上跟剛剛一樣,但要稍微改一下資料庫,HTML 也是用一樣的,路徑改一點點就好。

helper.py

def get_user_by_username(username):
    user = Users.query.filter_by(username=username).first()
    return render_user_data(user.id)

views.py


@user_bp.route("/@<username>/posts", methods=["GET"])
@login_required
def user_posts_page(username):
    user = get_user_by_username(username)
    posts = get_posts(user["id"])
    return render_template("posts.html", posts=posts)

基本上就是用使用者名稱把他整個物件都撈出來,然後當成 get_posts 的篩選器。

/post/

接下來看看瀏覽貼文的介紹,我們這次真的要從資料庫開始寫起。

def add_comment(user_id, post_id, content):
    comment = Comments(user_id, post_id, content)
    db.session.add(comment)
    db.session.commit()

def get_comments(post_id):
    comments = Comments.query.filter_by(post_id=post_id).all()
    return [
        {
            "id": comment.id,
            "author_id": comment.author_id,
            "post_id": comment.post_id,
            "content": comment.content,
        }
        for comment in comments
    ]

我們需要新增留言和得到留言,但我們這次就不多驗證了,抓留言的部分要轉成 dict。

接下來輪到 HTML,在這裏面需要放蠻多東西的。

post.html

{% extends "base.html" %}

{% block title %}{{ post['title'] }}{% endblock %}

{% block content %}
<form action="/post/{{ post['id'] }}" method="post">
    {{ form.csrf_token }}
    {{ form.content }}
    {{ form.submit }}
</form>
<div>
    <div>
        <div>{{ post['author_id'] }}</div>
        <div>{{ post['title'] }}</div>
        <div>{{ post['description'] }}</div>
        <div>{{ post['time'] }}</div>
        <div>
            {{ post['content'] | markdown }}
        </div>
    </div>
</div>
<div>
{% for comment in comments %}
    {{ comment['author_id'] }}
    {{ comment['content'] }}
{% endfor %}
</div>
{% endblock %}

裡面有一個表單,就是之前寫的新增留言的表單,接下來放的是貼文內容,比較特別的是我們終於用到 | markdown 了,這是 Flask-Markdown 的功勞,最後我們放了一堆 comments,就是從剛剛 get_comments 拿到的。

最後我們來到路徑本身。


@user_bp.route("/post/<int:post_id>", methods=["GET", "POST"])
@login_required
def view_post_page(post_id):
    form = AddCommentForm()
    if request.method == "GET":
        post = render_post(post_id)
        comments = get_comments(post_id)
        return render_template("post.html", post=post, comments=comments, form=form)
    if request.method == "POST":
        if form.validate_on_submit():
            add_comment(current_user.id, post_id, form.content.data)
            flash("Comment added.")
        else:
            for _, errors in form.errors.items():
                for error in errors:
                    flash(error, category="alert")
        return redirect(url_for("user.view_post_page", post_id=post_id))

基本上就是類似的程式碼,但這次貼文跟留言都要抓到。

/comments

在最後,我們來到了留言的 dashboard。

def get_user_comments(user_id):
    comments = Comments.query.filter_by(author_id=user_id).all()
    return [
        {
            "id": comment.id,
            "author_id": comment.author_id,
            "post_id": comment.post_id,
            "content": comment.content,
        }
        for comment in comments
    ]

他非常明顯跟剛剛的 get_comments 很接近,幾乎是複製貼上,只是改成了 author_id

接下來是 HTML 的部分。

comments.html


{% extends "base.html" %}

{% block title %}comments{% endblock %}

{% block content %}
<div>
{% for comment in comments %}
    {{ comment['author_id'] }}
    {{ comment['post_id'] }}
    {{ comment['content'] }}
{% endfor %}
</div>
{% endblock %}

基本上他跟剛剛最下面差不多,只是加上了 comment['post_id'],也可以在這邊加個連結連到那則貼文去。

@user_bp.route("/comments", methods=["GET"])
@login_required
def comments_dashboard_page():
    comments = get_user_comments(current_user.id)
    return render_template("comments.html", comments=comments)

最後來到路徑的部分,非常簡單,就是把留言抓出來然後丟給 HTML 處理好,就結束了。


上一篇
Day 26 實作 user_bp (4)
下一篇
Day 28 實作 admin_bp (1)
系列文
Flask30

尚未有邦友留言

立即登入留言