【百度云搜索,搜各种资料:http://www.81ad.cn】
Flask 构建微电影视频网站
已上线演示地址: http://movie.tbquan.cn
标签管理
标签添加
创建标签添加表单
在app/admin/forms.py中增加
class TagForm(FlaskForm):
name = StringField(
label='名称',
validators=[
DataRequired('标签名称不能为空!')
],
description='标签',
render_kw={
'class': "form-control",
'id': "input_name",
'placeholder': "请输入标签名称!"
}
)
submit = SubmitField(
label='添加',
render_kw={
'class': "btn btn-primary"
}
)
消息分类闪现,过滤闪现消息
参考文档: http://docs.jinkan.org/docs/flask/patterns/flashing.html
提交表单,查询Tag
数据库,这儿用到了flash的分类闪现,过滤闪现消息
- 如果查询结果数量为1,则表明标签名称存在,并使用flash进行提示,返回添加标签页面
{% with msgs = get_flashed_messages(category_filter=['ok']) %}
{% if msgs %}
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-check"></i> 成功!</h4>
{% for msg in msgs %}
<p>{{ msg }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
- 如果标签不存在,就能添加到数据库,添加成功后也返回一条成功的消息,并跳转为添加标签页面
{% with msgs = get_flashed_messages(category_filter=['err']) %}
{% if msgs %}
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-ban"></i> 失败!</h4>
{% for msg in msgs %}
<p>{{ msg }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
修改tag_add视图中逻辑处理
视图逻辑如下
from app.admin.forms import LoginFrom, TagForm
from app.models import Admin, Tag
from app import db
@admin.route("/tag/add/", methods=['GET', 'POST'])
@admin_login_require
def tag_add():
form = TagForm()
if form.validate_on_submit():
data = form.data
tag_num = Tag.query.filter_by(name=data['name']).count()
if tag_num == 1:
flash('标签名称已存在!', category='err')
return redirect(url_for('admin.tag_add'))
# 如果标签不存在,就添加到数据库
tag = Tag(
name=data['name']
)
db.session.add(tag)
db.session.commit()
# 提交完成后也返回一条成功的消息
flash('标签添加成功!', category='ok')
return redirect(url_for('admin.tag_add'))
return render_template('admin/tag_add.html', form=form)
修改tag_add.html页面的表单
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">添加标签</h3>
</div>
<form role="form" method="post">
<div class="box-body">
{% with msgs = get_flashed_messages(category_filter=['ok']) %}
{% if msgs %}
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-check"></i> 成功!</h4>
{% for msg in msgs %}
<p>{{ msg }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% with msgs = get_flashed_messages(category_filter=['err']) %}
{% if msgs %}
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-ban"></i> 失败!</h4>
{% for msg in msgs %}
<p>{{ msg }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<div class="form-group">
{#<label for="input_name">标签名称</label>#}
{#<input type="text" class="form-control" id="input_name" placeholder="请输入标签名称!">#}
<label for="input_name">{{ form.name.label }}</label>
{{ form.name }}
{% for err in form.name.errors %}
<div class="col-md-12" style="color: red">{{ err }}</div>
{% endfor %}
</div>
</div>
{{ form.csrf_token }}
<div class="box-footer">
{#<button type="submit" class="btn btn-primary">添加</button>#}
{{ form.submit }}
</div>
</form>
</div>
标签添加成功页面提示如下:
标签已存在页面提示如下
查询数据库结果如下
mysql> select * from tag;
+----+--------+---------------------+
| id | name | add_time |
+----+--------+---------------------+
| 1 | 科幻 | 2018-10-18 13:30:14 |
+----+--------+---------------------+
1 row in set (0.00 sec)
mysql> select * from tag;
+----+--------+---------------------+
| id | name | add_time |
+----+--------+---------------------+
| 1 | 科幻 | 2018-10-18 13:30:14 |
| 2 | 动作 | 2018-10-18 21:40:31 |
+----+--------+---------------------+
2 rows in set (0.00 sec)
第一条,他的add_time
总是和实际添加时间相差8小时,是因为,在models.py模型中使用了datetime.datetime.utcnow
,需要修改为datetime.datetime.now
,这样存入数据库就是本地时间了
标签列表
修改tag_list增加标签显示和分页
per_page=1
每一页显示一条数据,因为测试数据较少,后面再做修改。
@admin.route("/tag/list/<int:page>/", methods=['GET'])
@admin_login_require
def tag_list(page=None):
if page is None:
page = 1
# 设置per_page每页显示多少个数据
page_tags = Tag.query.order_by(Tag.add_time.desc()).paginate(page=page, per_page=1)
return render_template('admin/tag_list.html', page_tags=page_tags)
修改tag_list.html遍历显示标签列表
<table class="table table-hover">
<tbody>
<tr>
<th>编号</th>
<th>名称</th>
<th>添加时间</th>
<th>操作事项</th>
</tr>
{% for tag in page_tags.items %}
<tr>
<td>{{ tag.id }}</td>
<td>{{ tag.name }}</td>
<td>{{ tag.add_time }}</td>
<td>
<a class="label label-success">编辑</a>
<a class="label label-danger">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
访问 http://127.0.0.1:5000/admin/tag/list/1/ 报错
需要修改base.html中的标签列表增加分页页码
<li id="g-2-2">
<a href="{{ url_for('admin.tag_list') }}">
<i class="fa fa-circle-o"></i> 标签列表
</a>
</li>
<!--修改为下面的-->
<li id="g-2-2">
<a href="{{ url_for('admin.tag_list', page=1) }}">
<i class="fa fa-circle-o"></i> 标签列表
</a>
</li>
创建pagination.html显示分页模块
在app/templates/admin/目录下创建pagination.html文件
将tag_list.html中的分页模块复制到pagination.html中,因为后台所有内容的分页都是相同的,单独取出来用于多个页面的调用。
{% macro render_pagination(pagination, url_route) %}
<!--pagination为分页数据,url为指定分页的路由,需要给路由带上page参数,指定页数-->
<ul class="pagination pagination-sm no-margin pull-right">
<li><a href="{{ url_for(url_route, page=1) }}">首页</a></li>
{% if pagination.has_prev %}
<li><a href="{{ url_for(url_route, page=pagination.prev_num) }}">上一页</a></li>
{% endif %}
{%- for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
<li><a href="{{ url_for(url_route, page=page) }}">{{ page }}</a></li>
{% else %}
<li class="active"><a>{{ page }}</a></li>
{% endif %}
{% endif %}
{%- endfor %}
{% if pagination.has_next %}
<li><a href="{{ url_for(url_route, page=pagination.next_num) }}">下一页</a></li>
{% endif %}
<li><a href="{{ url_for(url_route, page=pagination.pages) }}">尾页</a></li>
</ul>
{% endmacro %}
修改tag_list.html导入分页模块
<div class="box-footer clearfix">
<!--页码模块-->
{% import 'admin/pagination.html' as pg %}
{{ pg.render_pagination(page_tags, 'admin.tag_list') }}
</div>
测试完成后将tag_list
视图中的per_page
分页都改为10条。
标签删除
参考链接: http://www.pythondoc.com/flask-sqlalchemy/queries.html#id2
创建tag_delete标签删除视图
在app/admin/views.py中添加标签删除视图
@admin.route("/tag/delete/<int:delete_id>/", methods=['GET'])
@admin_login_require
def tag_delete(delete_id=None):
if delete_id:
tag = Tag.query.filter_by(id=delete_id).first_or_404()
db.session.delete(tag)
db.session.commit()
# 删除后闪现消息
flash('删除标签成功!', category='ok')
return redirect(url_for('admin.tag_list', page=1))
修改tag_list.html删除标签链接和提示
在表格顶部添加消息闪现提示框,修改删除按钮的链接,以标签的id
为参数
{% with msgs = get_flashed_messages(category_filter=['ok']) %}
{% if msgs %}
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-check"></i> 成功!</h4>
{% for msg in msgs %}
<p>{{ msg }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<a class="label label-danger" href="{{ url_for('admin.tag_delete', delete_id=tag.id) }}">删除</a>
新建一个标签,然后点击删除,就会弹出删除成功提示信息。
编辑标签
类似于添加标签,只是在修改之前需要将该数据查询出来,我们可以直接复制tag_add
的内容做修改。
创建tag_update视图编辑标签
复制tag_add
的内容做修改
@admin.route("/tag/update/<int:update_id>/", methods=['GET', 'POST'])
@admin_login_require
def tag_update(update_id=None):
form = TagForm()
tag = Tag.query.get_or_404(update_id) # 首先查询到该标签,用主键查询,如果不存在,则返回404
if form.validate_on_submit():
data = form.data
tag_num = Tag.query.filter_by(name=data['name']).count()
if tag_num == 1:
flash('标签名称已存在!', category='err')
return redirect(url_for('admin.tag_update', update_id=update_id))
# 如果标签不存在,就进行修改
tag.name = data['name']
db.session.commit()
# 提交完成后也返回一条成功的消息
flash('标签修改成功!', category='ok')
return redirect(url_for('admin.tag_update', update_id=update_id))
return render_template('admin/tag_update.html', form=form, tag=tag)
为了编辑和删除可以使用相同的标签,统一将submit按钮名称修改为提交
创建tag_update.html编辑标签模板
直接复制tag_add.html
做一些修改,增加name
表单的初始值{{ form.name(value=tag.name) }}
,意思就是在name表单中设置value
为以前的标签名称。
模板代码为
{% extends 'admin/base.html' %}
{% block content %}
<section class="content-header">
<h1>微电影管理系统</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i> 标签管理</a></li>
<li class="active">修改标签</li>
</ol>
</section>
<section class="content" id="showcontent">
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">修改标签</h3>
</div>
<form role="form" method="post">
<div class="box-body">
{% with msgs = get_flashed_messages(category_filter=['ok']) %}
{% if msgs %}
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-check"></i> 成功!</h4>
{% for msg in msgs %}
<p>{{ msg }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% with msgs = get_flashed_messages(category_filter=['err']) %}
{% if msgs %}
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h4><i class="icon fa fa-ban"></i> 失败!</h4>
{% for msg in msgs %}
<p>{{ msg }}</p>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<div class="form-group">
{#<label for="input_name">标签名称</label>#}
{#<input type="text" class="form-control" id="input_name" placeholder="请输入标签名称!">#}
<label for="input_name">{{ form.name.label }}</label>
{{ form.name(value=tag.name) }}
{% for err in form.name.errors %}
<div class="col-md-12" style="color: red">{{ err }}</div>
{% endfor %}
</div>
</div>
{{ form.csrf_token }}
<div class="box-footer">
{#<button type="submit" class="btn btn-primary">添加</button>#}
{{ form.submit }}
</div>
</form>
</div>
</div>
</div>
</section>
{% endblock %}
{% block js %}
<script>
// 激活菜单栏
$(document).ready(function () {
$("#g-2").addClass('active');
$("#g-2-1").addClass('active');
})
</script>
{% endblock %}
创建一个ABC
的测试标签,然后点击编辑
修改为数据库中已存在的标签,比如科幻
修改为不存在的标签
查看标签列表