Day 25 实作 user_bp (3)

前言

我们今天还是没有离开 user_bp,我们要来弄写文章的页面,也就是 markdown 上场的日子。

/post/add

首先一样要先来处理一下资料库的部分,需要一个加入新贴文的函式。

def add_post(user_id, title, description, content):
    post = Posts(user_id, title, description, content)
    try:
        db.session.add(post)
        db.session.commit()
        return True
    except:
        return False

之前都是使用 Users 这个物件,这次要换成用 Posts 了。他会需要传入一些贴文的基本资料,然後把他加入资料库,如果有错误的话就代表他标题重复了 (空值的部分已经让 Flask-WTF 处理掉了)。

接下来是 HTML 的部分,他有一些些跟一般表单不一样的地方。

write.html

{% extends "base.html" %}

{% block title %}Post{% endblock %}

{% block content %}
{{ pagedown.include_pagedown() }}
<form action="{{ route }}" method="post">
    {{ form.csrf_token }}
    {{ form.title }}
    {{ form.description }}
    {{ form.content }}
    {{ form.submit }}
</form>
{% endblock %}

他有一个 {{ pagedown.include_pagedown() }},这是用来引入外部 JS 来及时显示 markdown 用的。要注意它是 pagedown 的东西,而不是 form,而这个 pagedown 就是一开始在 create_app 里面初始化用的那个。接下来会看到有一个 route 变数,这样 render_template 的时候就可以传入表单的提交路径。

接下来就跟之前差不多了,比较可以看一下的是 form.content,我们用的是最直接简单的方法,但也可以稍微调整他,有兴趣的话可以去他的GitHub repo 看看范例。

最後就要来看路径了,基本上跟之前的结构都一样。

views.py

@user_bp.route("/post/add", methods=["GET", "POST"])
@login_required
def add_post_page():
    form = AddPostForm()
    if request.method == "GET":
        return render_template("write.html", form=form, route="/post/add")
    if request.method == "POST":
        if form.validate_on_submit():
            title = form.title.data
            description = form.description.data
            content = form.content.data
            if add_post(current_user.id, title, description, content):
                flash("Add post.")
                return redirect(url_for("user.dashboard_page"))
            else:
                flash("The title has been used.")
                return redirect(url_for("user.add_post_page"))
        else:
            for _, errors in form.errors.items():
                for error in errors:
                    flash(error, category="alert")
            return redirect(url_for("user.add_post_page"))

差不多就是把栏位都抓出来,然後 add_post,没问题就跳到 dashboard,有问题就继续待在这里。但是在 render_template 的时候,我们加入了一个 route,就是刚刚 write.html 里面的,决定表单要送去哪。

/post/edit

写完文章就要来改文章,所以接下来我们来处理编辑文章的页面。一样,先来看看资料库。


def edit_post(post_id, title, description, content):
    post = Posts.query.filter_by(id=post_id)
    try:
        data = {"title": title, "description": description, "content": content}
        post.update(data)
        db.session.commit()
        return True
    except:
        return False


def render_post(post_id):
    post = Posts.query.filter_by(id=post_id).first()
    return {
        "id": post.id,
        "author_id": post.author_id,
        "title": post.title,
        "description": post.description,
        "content": post.content,
        "comments": [
            {
                "author_id": comment.author_id,
                "content": comment.content,
            }
            for comment in post.comments
        ],
    }

这里有 edit_postrender_post 两个函式,前者是用来编辑文章,也就是把现有的文章抓出来再修改内容,所以用 post_id 当参数;而後者是把文章转成 dict 送出来。

依照惯例,我们应该要来写 HTML,但这次不需要,因为我们可以直接拿刚刚的 write.html 来用。所以我们可以直接进入路径的部分,可想而知,也会跟刚刚十分类似。

@user_bp.route("/post/edit/<int:post_id>", methods=["GET", "POST"])
@login_required
def edit_post_page(post_id):
    post_data = render_post(post_id)
    form = AddPostForm(
        title=post_data["title"],
        description=post_data["description"],
        content=post_data["content"],
    )
    if request.method == "GET":
        return render_template("write.html", form=form, route=f"/post/edit/{post_id}")
    if request.method == "POST":
        if form.validate_on_submit():
            title = form.title.data
            description = form.description.data
            content = form.content.data
            if edit_post(post_id, title, description, content):
                flash("Post edited.")
                return redirect(url_for("user.dashboard_page"))
            else:
                flash("The title has been used.")
                return redirect(url_for("user.edit_post_page"))
        else:
            for _, errors in form.errors.items():
                for error in errors:
                    flash(error, category="alert")
            return redirect(url_for("user.edit_post_page"))

这里有比较不同的部分是在最前面我们先用刚刚的 render_post 把贴文的资料送出来,然後在建立表单的时候就直接把资料传进去,就像昨天弄使用者设定页面一样。接下来就十分类似,传不同的 route 给 jinja 处理,後面就都一样了。这边的 url_for 多了一个 post_id 的参数,会有他是因为这个编辑文章的页面有一个 post_id 的变数,如果不指定的话,flask 会无所适从,然後就喷错误了。

References

Create dynamic URLs in Flask with url_for()
Flask-PageDown


<<:  Kotlin 语言

>>:  框架与挑选实作的阶段 | ML#Day17

# Day 17 Physical Memory Model (二)

文件 Physical Memory Model 翻译: SPARSEMEM ========= S...

C# 鸡础观念- 目录

[Day1]C# 鸡础观念- C#简介 [Day2]C# 鸡础观念- 与C#开发千里来相见 [Da...

DAY8 MongoDB 批次操作(bulk wirte) 与 Operators

DAY8 MongoDB 批次操作(bulk wirte) 与 Operators bulk wri...

【day13】连续上班日做便当2

今天的便当是无淀粉系列 主菜是鲜甜的肉束尾 其实我本人很害怕猪肉的腥味 但男友妈妈准备的食材都很好 ...

小小聊一下 JDK跟JRE 吧!

来看看昨天的问题吧!顺便订个顺序~ javac 这个工具哪里来的呢? static 代表什麽意思呢?...