关于博主
努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!
微信公众号: 啃饼思录
![](https://img.haomeiwen.com/i8964398/e5729d3e50344ba3.jpg)
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
:
![](https://img.haomeiwen.com/i8964398/1df230c892fb53a2.png)
记得在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 %}
![](https://img.haomeiwen.com/i8964398/d5274e79c71a8219.png)
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 %}
就是这样:
![](https://img.haomeiwen.com/i8964398/b78bb6d46fa669bf.png)
运行一下我们的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循环的遍历:
![](https://img.haomeiwen.com/i8964398/da3301c9cce86c9e.png)
然后就是分页功能了,我们参考之前在标签列表页面的配置,打开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 %}
放在这个位置:
![](https://img.haomeiwen.com/i8964398/0e45aebb89f51752.png)
然后修改删除的跳转链接:
<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) }}
就是这里:
![](https://img.haomeiwen.com/i8964398/ff3912dea133b403.png)
![](https://img.haomeiwen.com/i8964398/3d6ae2fe8d10c1c7.png)
还要在movie_list里面修改页面的跳转:
<a href="{{ url_for('admin.movie_edit', id=v.id) }}" class="label label-success">编辑</a>
然后运行一下我们的manage.py文件,发现封面图片不显示:
![](https://img.haomeiwen.com/i8964398/d855382199c17182.png)
![](https://img.haomeiwen.com/i8964398/b91ffc40180b7349.png)
然后刷新发现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对应第七篇。
网友评论