Day 29 实作 admin_bp (2)

前言

快要结束了,今天要继续写 admin_bp。今天的内容会用到 JS,但我不会多加解释。

posts & comments

我们直接把 admin_dashboard_posts_backendadmin_dashboard_comments_backend 一起看,,因为他们真的很接近,一样从资料库开始。

def delete_post_admin(post_id):
    post = Posts.query.filter_by(id=post_id).first()
    comments = Comments.query.filter_by(post_id=post_id).all()
    db.session.delete(post)
    for comment in comments:
        db.session.delete(comment)
    db.session.commit()

def delete_comment_admin(comment_id):
    comment = Comments.query.filter_by(id=comment_id).first()
    db.session.delete(comment)
    db.session.commit()

虽然两个都是删除,但删除贴文比较麻烦一点,因为留言是附在贴文下面的,所以要连着留言一起删掉才行。

在进入 HTML 之前,我们要先看看 JS。

admin.js

function del_post(post_id) {
    $.ajax({
        url: "/admin_dashboard_posts_backend",
        type: "delete",
        data: JSON.stringify({ "post_id": post_id }),
        dataType: "json",
    })
        .always(function (r) {
            if (r.status == 200) {
                alert("OK.", "success");
            }
            else {
                alert("Error.", "alert");
            }
        })
}

function del_comment(comment_id) {
    $.ajax({
        url: "/admin_dashboard_comments_backend",
        type: "delete",
        data: JSON.stringify({ "comment_id": comment_id }),
        dataType: "json",
    })
        .always(function (r) {
            if (r.status == 200) {
                alert("OK.", "success");
            }
            else {
                alert("Error.", "alert");
            }
        })
}

这里我们使用了 jquery 来做 ajax,在使用者按下删除按钮之後就送出 request 让後端删除。

接下来是 HTML,基本上就是昨天写好的档案,只是要稍微加一些东西。

admin_dashboard_comments.html

{% block extra_import %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="/static/admin.js"></script>
{% endblock %}

<button onclick="del_comment({{ comment['id'] }});">Delete</button>

admin_dashboard_posts.html

{% block extra_import %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="/static/admin.js"></script>
{% endblock %}

<button onclick="del_post({{ post['id'] }});">Delete</button>

我们多引入了刚刚写的 admin.js 以及 jquery 的 JS 档案。接着我们调整了一下删除的按钮,把他多加了一个 onclick 来执行刚刚写的 JS。

最後要看到路径的部分,两个非常接近。

@admin_bp.route("/admin_dashboard_posts_backend", methods=["DELETE"])
def admin_dashboard_posts_backend():
    data = request.get_json(force=True)
    post_id = data["post_id"]
    try:
        delete_post_admin(post_id)
        return "OK"
    except:
        abort(400)


@admin_bp.route("/admin_dashboard_comments_backend", methods=["DELETE"])
def admin_dashboard_comments_backend():
    data = request.get_json(force=True)
    comment_id = data["comment_id"]
    try:
        delete_comment_admin(comment_id)
        return "OK"
    except:
        abort(400)

在这边我们又看到 request 并用了他的 get_json 函式。这边加了一个 force=True,是因为 flask 会侦测 request 的 MIME type,如果不是 JSON 他就会不让你 parse,加了这个参数之後他不管如何就是会 parse,但如果内容不是 JSON 的话他还是会喷错误。接下来就是尝试删除,不成功的话就 abort

manage_user

最後要做的部分是管理使用者页面的更新和删除按钮。一样先从资料库看起。

def delete_user(user_id):
    user = Users.query.filter_by(id=user_id).first()
    posts = Posts.query.filter_by(author_id=user_id).all()
    for post in posts:
        delete_post_admin(post)
    comments = Comments.query.filter_by(author_id=user_id).all()
    for comment in comments:
        db.session.delete(comment)
    db.session.delete(user)
    db.session.commit()

这边只有删除的,因为更新的函式在之前写过了。跟刚刚删除贴文类似,我们也需要把使用者的贴文和留言一起删掉。

再来一样先看看 JS,更新的部分跟刚刚稍微有些不同。

admin.js

function del_user(user_id) {
    $.ajax({
        url: "/manage_user_backend",
        type: "delete",
        data: JSON.stringify({ "user_id": user_id }),
        dataType: "json",
    })
        .always(function (r) {
            if (r.status == 200) {
                alert("OK.", "success");
            }
            else {
                alert("Error.", "alert");
            }
        })
}

function update_user(element) {
    var parent = element.parentElement;
    var user_id = parent.children[0].innerText;
    var email = parent.children[2].value;
    var is_admin = parent.children[3].checked;
    var data = { "user_id": user_id, "username": username, "email": email, "is_admin": is_admin }
    $.ajax({
        url: "/manage_user_backend",
        type: "patch",
        data: JSON.stringify(data),
        dataType: "json",
    })
        .always(function (r) {
            if (r.status == 200) {
                alert("OK.", "success");
            }
            else {
                alert("Error.", "alert");
            }
        })
}

光看这样子应该无法理解 update_userelement 在干嘛,所以我们直接看看 HTML,JS 的引入就不重复打了。

manage_user.html

<span>{{ user['id'] }}</span>
<span>{{ user['username'] }}</span>
<input type="email" value="{{ user['email'] }}">
<input type="checkbox" {% if user['is_admin'] %} checked {% endif %}>
<input type="text" value="{{ user['introduction'] }}">
<span>{{ user['register_time'] }}</span>
<button onclick="del_user({{ user['id'] }});">Delete</button>
<button onclick="update_user(this);">Update</button>

我们修改了底下的两个按钮,更新的按钮直接把自己这个 element 传入 JS,所以刚刚看到的 element 就是这个按钮。然後在 update_user 里面就去把每个栏位的值抓出来,丢给後端 python 处理。

最後来看到路径。

@admin_bp.route("/manage_user_backend", methods=["PATCH", "DELETE"])
def manage_user_backend():
    if request.method == "PATCH":
        data = request.get_json(force=True)
        if (
            update_user_data(
                data["user_id"], email=data["email"], is_admin=data["is_admin"]
            )
            == True
        ):
            return "OK"
        else:
            abort(400)
    if request.method == "DELETE":
        data = request.get_json(force=True)
        user_id = data["user_id"]
        try:
            delete_user(user_id)
            return "OK"
        except:
            abort(400)

因为有更新和删除两个功能,所以要先判断 request.method,然後再分别去更新,有问题的话就 abort(400)


<<:  JavaScript入门 Day24_物件1

>>:  [Day 14] Audit perfomance — 模型也要期末稽核༼ಢ_ಢ༽

归纳的方法

正式开启『 优雅的 Ruby 』的学习模式! 上回提到我们要用这本书来快乐学习, 透过重构的技巧进行...

30天轻松学会unity自制游戏-往前移动

用最简单的方式Ctrl+C&Ctrl+V把场景往上延伸,Ctrl+D也可以直接复制此物件,看...

Day 27 - 不安全的登入机制

出於书本 Chapter 14. Web sites and Application 不安全的登入机...

DAY 23 Typography, Hover 以及 Extend

随着内容越来越多,结构更加复杂,是时候来整理一下关於字型的配置,这次我们来新增一个 _typogra...

虹语岚访仲夏夜-3(专业的小四篇)

『不是不是,你啥意思啊,不知道细节,找我参加什麽啊? 』 「我主管说,如果找你的话,我明年有机会加薪...