美文网首页利用Flask搭建微电影视频网站
利用Flask搭建微电影视频网站(七):电影管理

利用Flask搭建微电影视频网站(七):电影管理

作者: 啃饼小白 | 来源:发表于2018-09-10 09:48 被阅读39次

关于博主

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

                                      微信公众号:  啃饼思录
                                    QQ: 2810706745(啃饼小白)

写在前面

本篇笔记,我们介绍电影管理,这个和前面介绍的标签管理差不多,话不多说,开始学习吧。

本篇笔记对应上传的仓库为:https://github.com/licheetools/movie对应第七篇。

电影管理

包括添加电影和电影列表这两个模块,下面我们先介绍添加电影这个功能的实现。

使用到的内容

我们将使用到的内容有:
模型:Movie
表单: MovieForm
请求方法: GET POST
访问控制: @admin_login_req

1、添加表单验证字段

打开forms.py,我们定义Form字段,注意因为是标签添加模块,所以对应的html页面就是movie_add.html,而且我们在forms.py里面定义的字段必须与movie_add.html里面的保持一致!

from wtforms import FileField, TextAreaField, SelectField
from app.models import Tag


# 添加电影
class MovieForm(FlaskForm):
    title= StringField(
        label="片名",
        validators=[
            DataRequired("片名不能为空")
        ],
        description="片名",
        render_kw={
            "class": "form-control",
            "id": "input_title",
            "placeholder": "请输入片名!!"
        }
    )
    url = FileField(
        label="文件",
        validators=[
            DataRequired("请上传文件!")
        ],
        description="文件",
    )
    info = TextAreaField(
        label="简介",
        validators=[
            DataRequired("简介不能为空")
        ],
        description="简介",
        render_kw={
            "class": "form-control",
            "rows=": 10,
        }
    )
    logo = FileField(
        label="封面",
        validators=[
            DataRequired("请上传封面!")
        ],
        description="封面",
    )
    star = SelectField(
        label="星级",
        validators=[
            DataRequired("请选择星级!")
        ],
        # 星级是整数型
        coerce=int,
        # 采用下拉选择的方式进行星级的选择
        choices=[(1, "1星级"), (2, "2星级"), (3, "3星级"), (4, "4星级"), (5, "5星级")],
        description="星级",
        render_kw={
            "class": "form-control",
        }
    )
    tag_id = SelectField(
        label="所属标签",
        validators=[
            DataRequired("请选择标签!")
        ],
        # 标签id也是整数型
        coerce=int,
        # 采用列表递归式来取出所有的标签
        choices=[(v.id, v.name)for v in Tag.query.all()],
        description="标签",
        render_kw={
            "class": "form-control",
        }
    )
    area = StringField(
        label="上映地区",
        validators=[
            DataRequired("请输入地区!")
        ],
        description="地区",
        render_kw={
            "class": "form-control",
            "id": "input_area",
            "placeholder": "请输入地区!"
        }
    )
    length = StringField(
        label="电影片长",
        validators=[
            DataRequired("请输入片长!")
        ],
        description="片长",
        render_kw={
            "class": "form-control",
            "id": "input_length",
            "placeholder": "请输入片长!"
        }
    )
    release_time = StringField(
        label="上映时间",
        validators=[
            DataRequired("请输入上映时间!")
        ],
        description="上映时间",
        render_kw={
            "class": "form-control",
            "id": "input_release_time",
            "placeholder": "请输入上映时间!"
        }
    )
    submit = SubmitField(
        '编辑',
        render_kw={
            "class": "btn btn-primary",
        }
    )

2、准备页面渲染字段

打开admin/views.py文件,我们修改movie_add函数:

from app.admin.forms import MovieForm
from app.models import Movie

# 电影添加
@admin.route('/movie/add')
@admin_login_req
def movie_add():
    form = MovieForm()
    return render_template("admin/movie_add.html", form=form)

3、后台页面传值显示

修改movie_add.html:


记得在submit的上面添加{{ form.csrf_token }},还有form提交的方法以及上传文件类别:
···
<form role="form" method="post" enctype="multipart/form-data">
···

4、后台页面错误信息提示

打开movie_tag.html页面,我们进行修改:

{% for err in form.title.errors %}
<div class="col-md-12">
<p style="color:red">{{ err }}</p>
</div>
{% endfor %}

5、文件上传

打开app/--init--.py文件,我们现在上传文件代码:

import os

app.config["UP_DIR"] = os.path.join(os.path.abspath(os.path.dirname(__file__)), "static/uploads/")

6、定义修改文件名称函数

在views.py文件新增以下代码:

from app import db, app
from werkzeug.utils import secure_filename
import os
import uuid
from datetime import datetime



# 修改文件名称
def change_filename(filename):
    fileinfo = os.path.splitext(filename)
    filename = datetime.now().strftime("%Y%m%d%H%M%S") + str(uuid.uuid4().hex) + fileinfo[-1]  # 文件后缀
    return filename

7、修改添加电影函数

# 电影添加
@admin.route('/movie/add', methods=["GET", "POST"])
@admin_login_req
def movie_add():
    form = MovieForm()
    if form.validate_on_submit():
        data = form.data
        file_url = secure_filename(form.url.data.filename)
        file_logo = secure_filename(form.logo.data.filename)
        if not os.path.exists(app.config["UP_DIR"]):  # 如果文件夹不存在
            os.makedirs(app.config["UP_DIR"])  # 新建对应的文件夹
            os.chmod(app.config["UP_DIR"], "rw")  # 给文件夹赋予读写的权限
        url = change_filename(file_url)
        logo = change_filename(file_logo)
        # 把他们进行保存到文件夹下面
        form.url.data.save(app.config["UP_DIR"] + url)
        form.logo.data.save(app.config["UP_DIR"] + logo)
        # 之后的url和logo就是我们修改之后的地址
        movie = Movie(
            title=data["title"],
            url=url,
            info=data["info"],
            logo=logo,
            star=data["star"],
            playnum=0,
            commentnum=0,
            tag_id=data["tag_id"],
            area=data['area'],
            release_time=data["release_time"],
            length=data["length"],
        )
        db.session.add(movie)
        db.session.commit()
        flash("添加电影成功!", "ok")
        return redirect(url_for("admin.movie_add"))
    return render_template("admin/movie_add.html", form=form)

8、添加电影成功消息闪现

打开movie_add.html页面,新增以下代码:

{% for msg in get_flashed_messages(category_filter=["ok"]) %}
<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>
 {{ msg }}
 </div>
 {% endfor %}
就是这样:

运行一下我们的manage.py发现报错:

builtins.TypeError
TypeError: an integer is required (got type str)

那是因为我们的星级和所属标签是Int类型,我们需要转换一下:

star= int(data["star"]),
tag_id=int(data["tag_id"]),

接着重新运行一下我们的manage.py文件,发现电影添加没有任何问题。

至此,我们添加电影的功能就介绍完了,下面介绍电影管理列表的配置!

电影管理列表的配置

电影管理列表的配置其实和我们之前配置的标签列表非常相似,所以我们介绍就快一点,打开admin/views.py文件,修改movie_list函数如下:

# 电影列表
@admin.route('/movie/list/<int:page>', methods=["GET"])
@admin_login_req
def movie_list(page=None):
    if page is None:
        page = 1
    # 查询的时候关联标签,采用join来加进去,多表关联用filter,过滤用filter_by
    page_data = Movie.query.join(Tag).filter(
        Tag.id == Movie.tag_id
    ).order_by(
        Movie.addtime.desc()
    ).paginate(page=page, per_page=10)
    return render_template("admin/movie_list.html", page_data=page_data)

接着去修改grid.html页面,修改gird中标签列表的url,为其添加参数page =1:

<a href="{{ url_for('admin.movie_list', page=1) }}">
       <i class="fa fa-circle-o"></i> 电影列表
 </a>
然后打开movie_list.htm页面,开始for循环的遍历:

然后就是分页功能了,我们参考之前在标签列表页面的配置,打开movie_list.html:

<ul class="pagination pagination-sm no-margin pull-right">
                            <li><a href="#">首页</a></li>
                            <li><a href="#">上一页</a></li>
                            <li><a href="#">1</a></li>
                            <li><a href="#">2</a></li>
                            <li><a href="#">3</a></li>
                            <li><a href="#">下一页</a></li>
                            <li><a href="#">尾页</a></li>
 </ul>

去掉上面一段代码,我们在开头导入刚才的admin_page.html文件,然后开始调用:

{% import "ui/admin_page.html" as pg %}

将下面的代码填充你刚才删除的那段的位置:

{{ pg.page(page_data, "admin.movie_list") }}

至此,关于电影列表的介绍就到此为止了!接下来是电影的删除和编辑!

电影的删除

打开views.py文件,我们在电影列表的下面新增以下代码:

# 电影删除
@admin.route('/movie/del/<int:id>', methods=["GET"])
@admin_login_req
def movie_del(id=None):
    movie = Movie.query.get_or_404(int(id))
    db.session.delete(movie)
    db.session.commit()
    flash("电影删除成功!", "ok")
    return redirect(url_for("admin.movie_list", page=1))

接着打开movie_list.html页面,我们复制提示成功的代码:

 {% for msg in get_flashed_messages(category_filter=["ok"]) %}
<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>
 {{ msg }}
 </div>
 {% endfor %}
放在这个位置:

然后修改删除的跳转链接:

<a href="{{ url_for('admin.movie_del', id=v.id) }}" class="label label-danger">删除</a>

然后就可以测试你的项目了!

电影的编辑

打开views.py文件,我们在电影列表的下面新增以下代码:

# 电影编辑
@admin.route('/movie/edit/<int:id>', methods=["GET", "POST"])
@admin_login_req
def movie_edit(id=None):
    form = MovieForm()   # 实例化一个TagForm,然后将form传递到前端页面去。
    movie = Movie.query.get_or_404(id)
    if form.validate_on_submit():
        data = form.data
        flash("修改电影成功!", "ok")
        return redirect(url_for("admin.movie_edit", id=movie.id))
    return render_template("admin/movie_edit.html", form=form, movie=movie)

接着在admin下面新建movie_edit.html页面,将movie_add.html页面全部添加进去,然后开始修改:将所有的添加字段改为修改,为form.title增加初值(value=movie.title):

{{ form.title(value=movie.title)}}

别忘了还有form.url,form.info,form.star,form.tag_id,form.area,form.release_time和form.length:

 {{ form.url(value=movie.url) }}

 {{ form.info(value=movie.info) }}

.......

注意form.logo的初值和其他不一样

{{ url_for('static',filename='uploads/'+ movie.logo) }}
就是这里: 还有js里面的也需要修改:

还要在movie_list里面修改页面的跳转:

<a href="{{ url_for('admin.movie_edit', id=v.id) }}" class="label label-success">编辑</a>
然后运行一下我们的manage.py文件,发现封面图片不显示: 将图片里的data-src修改为src:

然后刷新发现info,tag_id,star还是不行,我们需要重新配置这三个字段的初始值,去掉之前在movie_edit里面赋予的初始值(就是只有这种{{ form.info }},不带初值),我们直接在views.py文件里配置:

# 电影编辑
@admin.route('/movie/edit/<int:id>', methods=["GET", "POST"])
@admin_login_req
def movie_edit(id=None):
    form = MovieForm()   # 实例化一个TagForm,然后将form传递到前端页面去。
    movie = Movie.query.get_or_404(id)
    if request.method == "GET":
        form.info.data = movie.info
        form.tag_id.data = movie.tag_id
        form.star.data = movie.star
    if form.validate_on_submit():
        data = form.data
        flash("修改电影成功!", "ok")
        return redirect(url_for("admin.movie_edit", id=movie.id))
    return render_template("admin/movie_edit.html", form=form, movie=movie)

之后就是对修改的部分进行提交之后的保存:

movie.title = data["title"]
movie.info = data["info"]
movie.star = data["star"]
movie.tag_id = data["tag_id"]
movie.length = data["length"]
movie.area = data["area"]
movie.release_time = data["release_time"]
db.session.add(movie)
db.session.commit()
flash("修改电影成功!", "ok")

不过这还有一个问题,那就是片名的唯一性,我们不可能有同名的电影(现实里面是有的,但做不到完全一样,至少在演员,导演,剧情,上映时间肯定有一个不一样,但这里我们只限定片名不一样即可!)

片名的唯一性

打开views.py文件,我们修改电影编辑函数:

# 电影编辑
@admin.route('/movie/edit/<int:id>', methods=["GET", "POST"])
@admin_login_req
def movie_edit(id=None):
    form = MovieForm()   # 实例化一个TagForm,然后将form传递到前端页面去。
    form.url.validators = []    # 因为是编辑,所以首先必须是非空才需要验证
    form.logo.validators = []
    movie = Movie.query.get_or_404(int(id))
    if request.method == "GET":
        form.info.data = movie.info
        form.tag_id.data = movie.tag_id
        form.star.data = movie.star
    if form.validate_on_submit():
        data = form.data
        movie_count = Movie.query.filter_by(title=data["title"]).count()
        # 电影去重,唯一性
        if movie.title != data["title"] and movie_count == 1:
            flash("该影片已经存在了!", "err")
            return redirect(url_for("admin.movie_edit", id=id))
        # 如果文件夹不存在,那么就创建一个文件夹
        if not os.path.exists(app.config["UP_DIR"]):  # 如果文件夹不存在
            os.makedirs(app.config["UP_DIR"])  # 新建对应的文件夹
            os.chmod(app.config["UP_DIR"], "rw")  # 给文件夹赋予读写的权限

        # 如果视频文件修改了,就进行替换
        if form.url.data.filename != "":
            file_url = secure_filename(form.url.data.filename)
            movie.url = change_filename(file_url)
            form.url.data.save(app.config["UP_DIR"] + movie.url)

        # 如果图片文件修改了,就进行替换
        if form.logo.data.filename != "":
            file_logo = secure_filename(form.logo.data.filename)
            movie.logo = change_filename(file_logo)
            form.logo.data.save(app.config["UP_DIR"] + movie.logo)

        movie.title = data["title"]
        movie.info = data["info"]
        movie.star = data["star"]
        movie.tag_id = data["tag_id"]
        movie.length = data["length"]
        movie.area = data["area"]
        movie.release_time = data["release_time"]
        db.session.add(movie)
        db.session.commit()
        flash("修改电影成功!", "ok")
        return redirect(url_for("admin.movie_edit", id=movie.id))
    return render_template("admin/movie_edit.html", form=form, movie=movie)

接下来去movie_edit.html页面添加操作信息提示:

{% for msg in get_flashed_messages(category_filter=["ok"]) %}
<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>
          {{ msg }}
</div>
{% endfor %}


 {% for msg in get_flashed_messages(category_filter=["err"]) %}
 <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>
 {{ msg }}
</div>
 {% endfor %}

然后刷新一下我们的后台,发现关于电影这一功能是不是都能使用了!

至此,我们关于电影管理的介绍就到此为止了,感谢你的赏阅!!!

本篇笔记对应上传的仓库为:https://github.com/licheetools/movie对应第七篇。

相关文章

网友评论

    本文标题:利用Flask搭建微电影视频网站(七):电影管理

    本文链接:https://www.haomeiwen.com/subject/rdehgftx.html