14、Flask构建弹幕微电影网站-电影标签管理:增删查改

百度云搜索,搜各种资料: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>

标签添加成功页面提示如下:

BLOG_20181111_200359_19

标签已存在页面提示如下

BLOG_20181111_200432_94

查询数据库结果如下

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>
                &nbsp;
                <a class="label label-danger">删除</a>
            </td>
        </tr>
    {% endfor %}
    </tbody>
</table>

访问 http://127.0.0.1:5000/admin/tag/list/1/ 报错

BLOG_20181111_200443_95

需要修改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>

BLOG_20181111_200501_21

创建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>

BLOG_20181111_200508_36

测试完成后将tag_list视图中的per_page分页都改为10条。

BLOG_20181111_200524_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>

新建一个标签,然后点击删除,就会弹出删除成功提示信息。

BLOG_20181111_200536_19
BLOG_20181111_200548_74

编辑标签

类似于添加标签,只是在修改之前需要将该数据查询出来,我们可以直接复制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的测试标签,然后点击编辑

BLOG_20181111_200602_38

修改为数据库中已存在的标签,比如科幻

BLOG_20181111_200620_99

修改为不存在的标签

BLOG_20181111_200626_45

查看标签列表

BLOG_20181111_200638_15
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容