今天要开始写 admin_bp
,有蛮多部分跟之前很像。
先来看看 HTML 的部分。
admin_dashboard_posts.html
{% extends "base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<form action="/admin_dashboard/posts" method="post">
{{ form.csrf_token }}
{{ form.start }}
{{ form.end }}
{{ form.user_id }}
{{ form.submit }}
</form>
<div>
{% for post in posts %}
<div>
{{ post['author_id'] }}
<a href="/post/{{ post['id'] }}">{{ post['title'] }}</a>
{{ post['description'] }}
{{ post['time'] }}
<button>Delete</button>
</div>
{% endfor %}
</div>
{% endblock %}
基本上跟一般使用者的 dashboard 差不多,但 form
的部分新加入了一个 user_id
的栏位。在最後面有一个删除的按钮,它今天还不会登场。
接下来进入路径的部分,也一样跟使用者的 dashboard 类似,因为都有筛选器。
@admin_bp.route("/admin_dashboard/posts", methods=["GET", "POST"])
def admin_dashboard_posts_page():
filter_args = {}
if start := request.cookies.get("start"):
filter_args["start"] = datetime.datetime.strptime(start, "%Y-%m-%d")
if end := request.cookies.get("end"):
filter_args["end"] = datetime.datetime.strptime(end, "%Y-%m-%d")
if user_id := request.cookies.get("user_id"):
filter_args["user_id"] = user_id
form = AdminDashboardFilter(**filter_args)
if request.method == "GET":
posts = get_posts(**filter_args)
return render_template("admin_dashboard_posts.html", posts=posts, form=form)
if request.method == "POST":
response = make_response(redirect(url_for("admin.admin_dashboard_posts_page")))
if form.validate_on_submit():
cookies = []
if form.start.data:
cookies.append(("start", form.start.data.strftime("%Y-%m-%d")))
if form.end.data:
cookies.append(("end", form.end.data.strftime("%Y-%m-%d")))
if form.user_id.data:
cookies.append(("user_id", str(form.user_id.data)))
response.delete_cookie("start")
response.delete_cookie("end")
response.delete_cookie("user_id")
for cookie in cookies:
response.set_cookie(*cookie)
else:
for _, errors in form.errors.items():
for error in errors:
flash(error, category="alert")
return response
基本上就是直接从使用者 dashboard 抄过来的,只是多加一个 user_id
而已。但还是有一个小东西要注意一下,在拉出 user_id
的时候要把他转成字串,不然会喷错误。
接着来到留言的 dashboard,跟刚刚也是很接近,但要先来加一个资料库的函式。
def get_all_comments(user_id=None, start=None, end=None):
query = Comments.query
if user_id:
query = query.filter_by(user_id)
if start:
query = query.filter(Comments.time > start)
if end:
query = query.filter(Comments.time < end)
return [
{
"id": comment.id,
"author_id": comment.author_id,
"post_id": comment.post_id,
"content": comment.content,
}
for comment in query.all()
]
基本上就是把 get_posts
拿来这边改一下而已。
接下来是他的 HTML。
admin_dashboard_comments.html
{% extends "base.html" %}
{% block title %}comments{% endblock %}
{% block content %}
<form action="/admin_dashboard/comments" method="post">
{{ form.csrf_token }}
{{ form.start }}
{{ form.end }}
{{ form.user_id }}
{{ form.submit }}
</form>
<div>
{% for comment in comments %}
{{ comment['author_id'] }}
{{ comment['post_id'] }}
{{ comment['content'] }}
{{ comment['time'] }}
<button>Delete</button>
{% endfor %}
</div>
{% endblock %}
表单也是一样的,就是筛选器。跟刚刚一样,他也有删除的按钮。
最後来到路径的部分。
@admin_bp.route("/admin_dashboard/comments", methods=["GET"])
def admin_dashboard_comments_page():
filter_args = {}
if start := request.cookies.get("start"):
filter_args["start"] = datetime.datetime.strptime(start, "%Y-%m-%d")
if end := request.cookies.get("end"):
filter_args["end"] = datetime.datetime.strptime(end, "%Y-%m-%d")
if user_id := request.cookies.get("user_id"):
filter_args["user_id"] = user_id
form = AdminDashboardFilter(**filter_args)
if request.method == "GET":
comments = get_all_comments(**filter_args)
return render_template("admin_dashboard_comments.html", comments=comments, form=form)
if request.method == "POST":
response = make_response(redirect(url_for("admin.admin_dashboard_comments_page")))
if form.validate_on_submit():
cookies = []
if form.start.data:
cookies.append(("start", form.start.data.strftime("%Y-%m-%d")))
if form.end.data:
cookies.append(("end", form.end.data.strftime("%Y-%m-%d")))
if form.user_id.data:
cookies.append(("user_id", str(form.user_id.data)))
response.delete_cookie("start")
response.delete_cookie("end")
response.delete_cookie("user_id")
for cookie in cookies:
response.set_cookie(*cookie)
else:
for _, errors in form.errors.items():
for error in errors:
flash(error, category="alert")
return response
跟刚刚几乎一模一样,只是把贴文换成留言而已。
在今天的最後,我们要处理管理使用者的介面。一样先从资料库部分看起。
def get_all_users(user_id=None, username=None, start=None, end=None):
query = Users.query
if user_id:
query = query.filter_by(id=user_id)
if username:
query = query.filter_by(username=username)
if start:
query = query.filter(Users.register_time > start)
if end:
query = query.filter(Users.register_time < end)
return user_to_dict(query.all())
基本上都跟刚刚很接近,只是这里我们用已经写好的 user_to_dict
取代刚刚的 list comprehension。
接着是 HTML 的部分,基本上也蛮类似的。
manage_user.html
{% extends "base.html" %}
{% block title %}Manage User{% endblock %}
{% block content %}
<form action="/manage_user" method="post">
{{ form.csrf_token }}
{{ form.start }}
{{ form.end }}
{{ form.user_id }}
{{ form.username }}
{{ form.submit }}
</form>
<div>
{% for user in users %}
<div>
<span>{{ user['id'] }}</span>
<input type="text" value="{{ user['username'] }}">
<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>Delete</button>
<button>Update</button>
</div>
{% endfor %}
</div>
{% endblock %}
稍微不一样的是我们把单纯的显示出来变成了 input
,这样管理员才可以直接修改,里面没有加上密码的栏位,因为太烦了,而且也是可以想到的东西,就不在这边做。还有一个不一样的地方是 user['is_admin']
的部分,我们在那里用了一个 if 来判断他是不是管理员,如果是的话就把那个 checkbox 勾起来。
最後要看的是路径本身,基本上就是跟前面两个相同。
@admin_bp.route("/manage_user", methods=["GET", "POST"])
def manage_user_page():
filter_args = {}
if start := request.cookies.get("start"):
filter_args["start"] = datetime.datetime.strptime(start, "%Y-%m-%d")
if end := request.cookies.get("end"):
filter_args["end"] = datetime.datetime.strptime(end, "%Y-%m-%d")
if user_id := request.cookies.get("user_id"):
filter_args["user_id"] = user_id
if username := request.cookies.get("username"):
filter_args["username"] = username
form = UserFilterForm(**filter_args)
if request.method == "GET":
users = get_all_users(**filter_args)
return render_template("manage_user.html", users=users, form=form)
if request.method == "POST":
response = make_response(redirect(url_for("admin.manage_user_page")))
if form.validate_on_submit():
cookies = []
if form.start.data:
cookies.append(("start", form.start.data.strftime("%Y-%m-%d")))
if form.end.data:
cookies.append(("end", form.end.data.strftime("%Y-%m-%d")))
if form.user_id.data:
cookies.append(("user_id", str(form.user_id.data)))
if form.username.data:
cookies.append(("username", form.username.data))
response.delete_cookie("start")
response.delete_cookie("end")
response.delete_cookie("user_id")
response.delete_cookie("username")
for cookie in cookies:
response.set_cookie(*cookie)
else:
for _, errors in form.errors.items():
for error in errors:
flash(error, category="alert")
return response
要记得把 form
改掉,也要记得多一个栏位 username
。
<<: 调节磁碟和CPU的矛盾 - InnoDB的Buffer Pool
本系列已集结成书从 0 到 Webpack:学习 Modern Web 专案的建置方式,这是一本完...
表单 一般input、textarea、select(包含多重选择) 结构 最外层:Class中加上...
https://edm.bnext.com.tw/2021cpx/?utm_source=%E3%8...
谈到 Android 的 dependency injection (DI),大家一定会想到 Dag...
原始题目 Assume you are an awesome parent and want to ...