利用Flask搭建微电影视频网站(十四):前台后续开发
关于博主
努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!
微信公众号: 啃饼思录
QQ: 2810706745(啃饼小白)
写在前面
本篇笔记,我们将完成前台的后续开发,需要实现上映预告,标签筛选,电影搜索,电影播放,评论显示和收藏电影等功能。
本篇笔记对应上传的仓库为:https://github.com/licheetools/movie对应第十四篇。
上映预告
使用到的内容
我们将使用到的内容有:
模型:Preview
表单: 无
请求方法: GET
访问控制: 无
1、修改动画视图
打开views.py文件,我们修改一下动画视图:
from app.models import Preview
# 动画
@home.route('/animation/')
def animation():
data = Preview.query.all()
return render_template("home/animation.html", data=data)
2、配置animation页面
我们修改一下我们的animation.html页面:
标签筛选和电影分页
标签就是这里:
使用到的内容
我们将使用到的内容有:
模型:Tag ,Movie
表单: 无
请求方法: GET
访问控制: 无
1、编写视图函数
打开views.py文件,我们修改index函数:
from app.models import Tag
# 首页
@home.route('/')
def index():
tags = Tag.query.all()
movtag = request.args.get("movtag", 0) # 获取电影标签
star = request.args.get("star", 0) # 获取电影星级
ontime = request.args.get("ontime", 0) # 获取上映时间
playnum = request.args.get("playnum", 0) # 获取播放数量
commnum = request.args.get("commnum", 0) # 获取评论数量
return render_template("home/index.html", tags=tags)
2、进行标签和星级遍历
{% for v in tags %}
<a class="label label-info"><span
class="glyphicon glyphicon-tag"></span> {{ v.name }}</a>
{% endfor %}
{% for v in range(1,6) %}
<a class="label label-warning"><span class="glyphicon glyphicon-star"></span> {{ v }}</a>
{% endfor %}
3、构建参数字典
p = dict(
movtag=movtag,
star=star,
ontime=ontime,
playnum=playnum,
commnum=commnum
)
这是为了后面的筛选用,记得把p传进去!
4、配置筛选
我们对电影标签进行筛选,采用这种方式进行:
<a href="{{ url_for('home.index') }}?movtag={{ v.id }}&star={{ p['star'] }}&ontime={{ p['ontime'] }}&playnum={{ p['playnum'] }}&commnum={{ p['commnum'] }}"...</a>
也就是说除了当前所选之外,其余的我们都是采用获取字典属性的方法来获得相关属性。
电影星级:
<a href="{{ url_for('home.index') }}?movtag={{ p['movtag'] }}&star={{ v }}&ontime={{ p['ontime'] }}&playnum={{ p['playnum'] }}&commnum={{ p['commnum'] }}" ......</a>
上映时间:
<a href="{{ url_for('home.index') }}?movtag={{ p['movtag'] }}&star={{ p['star'] }}&ontime=1&playnum={{ p['playnum'] }}&commnum={{ p['commnum'] }}" .......最近</span></a>
<a href="{{ url_for('home.index') }}?movtag={{ p['movtag'] }}&star={{ p['star'] }}&ontime=2&playnum={{ p['playnum'] }}&commnum={{ p['commnum'] }}" ......更早</span></a>
我们这里用ontime的值1-2分别代表最近,更早。
播放数量:
<a href="{{ url_for('home.index') }}?movtag={{ p['movtag'] }}&star={{ p['star'] }}&ontime={{ p['ontime'] }}&playnum=1&commnum={{ p['commnum'] }}" ......从高到低</span></a>
<a href="{{ url_for('home.index') }}?movtag={{ p['movtag'] }}&star={{ p['star'] }}&ontime={{ p['ontime'] }}&playnum=2&commnum={{ p['commnum'] }}" ......从低到高</span></a>
我们这里用playnum的值1-2分别代表从高到低,从低到高。
评论数量:
<a href="{{ url_for('home.index') }}?movtag={{ p['movtag'] }}&star={{ p['star'] }}&ontime={{ p['ontime'] }}&playnum={{ p['playnum'] }}&commnum=1"......从高到低</span></a>
<a href="{{ url_for('home.index') }}?movtag={{ p['movtag'] }}&star={{ p['star'] }}&ontime={{ p['ontime'] }}&playnum={{ p['playnum'] }}&commnum=2" ......从低到高</span></a>
我们这里用commnum的值1-2分别代表从高到低,从低到高。
5、修改视图函数
我们打开views.py文件,继续完善我们的index视图:
from app.models import Movie
# 首页
@home.route("/<int:page>/", methods=["GET"])
@home.route("/", methods=["GET"])
def index(page=None):
tags = Tag.query.all()
page_data = Movie.query
movtag = request.args.get("movtag", 0) # 获取电影标签
if int(movtag) != 0:
page_data = page_data.filter_by(tag_id=int(movtag))
star = request.args.get("star", 0) # 获取电影星级
if int(star) != 0:
page_data = page_data.filter_by(star=int(star))
ontime = request.args.get("ontime", 0) # 获取上映时间
if int(ontime) != 0:
if int(ontime) == 1:
page_data = page_data.order_by(
Movie.addtime.desc()
)
else:
page_data = page_data.order_by(
Movie.addtime.asc()
)
playnum = request.args.get("playnum", 0) # 获取播放数量
if int(playnum) != 0:
if int(playnum) == 1:
page_data = page_data.order_by(
Movie.playnum.desc()
)
else:
page_data = page_data.order_by(
Movie.playnum.asc()
)
commnum = request.args.get("commnum", 0) # 获取评论数量
if int(commnum) != 0:
if int(commnum) == 1:
page_data = page_data.order_by(
Movie.commentnum.desc()
)
else:
page_data = page_data.order_by(
Movie.commentnum.asc()
)
if page is None:
page = 1
page_data = page_data.paginate(page=page, per_page=12)
p = dict(
movtag=movtag,
star=star,
ontime=ontime,
playnum=playnum,
commnum=commnum
)
return render_template("home/index.html", tags=tags, p=p, page_data=page_data)
6、进行列表显示和分页配置
打开搜索框,输入home.index
,我们在这些后面添加page=1
,一共5个地方:
如果少了运行就会报下面的错误:
werkzeug.routing.BuildError: Could not build url for endpoint 'home.index'. Did you forget to specify values ['page']?
分页的配置就2步:首先复制这个置于文件开头:
{% import "ui/home_page.html" as pg %}
接着复制下面的替换静态分页效果:
{{ pg.page(page_data, "home.index") }}
别放错位置哈:
电影搜索和电影分页
使用到的内容
我们将使用到的内容有:
模型:Movie
表单: 无
请求方法: GET
访问控制: 无
1、书写搜索视图函数
# 搜索页面
@home.route('/search/<int:page>/')
def search(page=None):
if page is None:
page = 1
key = request.args.get('key', '')
movie_count = Movie.query.filter(
Movie.title.ilike('%' + key + '%') # ilike可以进行模糊查询
).count()
page_data = Movie.query.filter(
Movie.title.ilike('%' + key + '%')
).order_by(
Movie.addtime.desc()
).paginate(page=page, per_page=10)
return render_template("home/search.html", key=key, movie_count=movie_count, page_data=page_data)
2、修改home和layout页面
为搜索电影加id="key_movie"
,与此同时为搜索添加id="do_search"
,还要删除搜索的链接href:
然后采用Jquery来控制搜索按钮,在JavaScript里面添加这段Jquery代码:
$("#do_search").click(function () {
var key = $("#key_movie").val();
location.href = "{{ url_for('home.search', page=1) }}?key=" + key;
});
这段Jquery代码的意思是说,当点击class="do_search"的搜索框时,就会去查询电影里面含有key的电影,并返回到search搜索结果列表页面。
注意这些操作都需要在home和layout页面进行,2个都要进行配置!!!
然后就是分页了,就2步:首先复制这个置于文件开头:
{% import "ui/home_page.html" as pg %}
接着复制下面的替换静态分页效果:
{{ pg.page(page_data, "home.search") }}
别放错位置哈!!!
电影详情和电影播放
使用到的内容
我们将使用到的内容有:
模型: Movie
表单: 无
请求方法: GET
访问控制: 无
1、编写播放视图
# 详情页面
@home.route('/play/<int:id>/')
def play(id=None):
movie = Movie.query.join(Tag).filter(
Tag.id == Movie.tag_id,
Movie.id == int(id)
).first_or_404()
return render_template("home/play.html", movie=movie)
2、添加电影id
打开搜索框,输入home.play
,我们在这些后面添加id=v.id
,一共3个地方:
3、修改播放页面显示
注意一下星级:
{% for val in range(1,movie.star+1) %}
<span class="glyphicon glyphicon-star" style="color:#FFD119"></span>
{% endfor %}
{% for val in range(1,5-movie.star) %}
<span class="glyphicon glyphicon-star-empty" style="color:#FFD119"></span>
{% endfor %}
还有底下的配置:
电影评论和电影统计
使用到的内容
我们将使用到的内容有:
模型:Movie User Comment
表单: CommentForm
请求方法: GET ,POST
访问控制: 需要登入
1、添加表单验证字段
# 添加评论
class CommentForm(FlaskForm):
content = TextAreaField(
label="内容",
validators=[
DataRequired("请输入内容!"),
],
description="内容",
render_kw={
"id": "input_content"
}
)
submit = SubmitField(
'提交评论',
render_kw={
"class": "btn btn-success",
"id": "btn-sub"
}
)
2、判断登入和是否显示评论框
打开play.html页面,我们修改成这样:
注意,是"user",不是user,这个一定要注意哈!!!
3、准备页面渲染字段
打开home/views.py文件,我们修改play函数:
from app.home.forms import CommentForm
# 详情页面
@home.route('/play/<int:id>/', methods=["GET", "POST"])
def play(id=None):
movie = Movie.query.join(Tag).filter(
Tag.id == Movie.tag_id,
Movie.id == int(id)
).first_or_404()
form = CommentForm()
if "user" in session and form.validate_on_submit():
data = form.data
return render_template("home/play.html", movie=movie, form=form)
4、前台页面传值显示以及操作信息提示
可以仿照后台的那些页面的配置来修改play.html:
5、继续完善我们的播放视图
from app.models import Comment
# 详情页面
@home.route('/play/<int:id>/', methods=["GET", "POST"])
def play(id=None):
movie = Movie.query.join(Tag).filter(
Tag.id == Movie.tag_id,
Movie.id == int(id)
).first_or_404()
movie.playnum = movie.playnum + 1
form = CommentForm()
if "user" in session and form.validate_on_submit():
data = form.data
comment = Comment(
content=data["content"], # 左侧字段与数据库Comment字段保持一致
movie_id=movie.id,
user_id=session["user_id"]
)
db.session.add(comment)
db.session.commit()
flash("添加评论成功!", "ok")
return redirect(url_for("home.play", id=movie.id))
movie.commentnum = movie.commentnum+1
db.session.add(movie)
db.session.commit()
return render_template("home/play.html", movie=movie, form=form)
然后你就可以去play.html页面添加我们的评论了!
评论分页及显示
我们继续修改我们的播放视图:
# 详情页面
@home.route('/play/<int:id>/<int:page>/', methods=["GET", "POST"])
def play(id=None, page=None):
movie = Movie.query.join(Tag).filter(
Tag.id == Movie.tag_id,
Movie.id == int(id)
).first_or_404()
if page is None:
page = 1
# 查询的时候关联标签,采用join来加进去,多表关联用filter,过滤用filter_by
page_data = Comment.query.join(
Movie
).join(
User
).filter(
Movie.id == movie.id,
User.id == Comment.user_id
).order_by(
Comment.addtime.desc()
).paginate(page=page, per_page=10)
movie.playnum = movie.playnum + 1
form = CommentForm()
if "user" in session and form.validate_on_submit():
data = form.data
comment = Comment(
content=data["content"], # 左侧字段与数据库Comment字段保持一致
movie_id=movie.id,
user_id=session["user_id"]
)
db.session.add(comment)
db.session.commit()
movie.commentnum = movie.commentnum + 1
db.session.add(movie)
db.session.commit()
flash("添加评论成功!", "ok")
return redirect(url_for("home.play", id=movie.id, page=1))
movie.commentnum = movie.commentnum+1
db.session.add(movie)
db.session.commit()
return render_template("home/play.html", movie=movie, form=form, page_data=page_data)
然后就是在index.html 和search.html页面添加page=1
:
接下来就是评论的遍历了,打开play.html页面,我们做如下修改:
别忘记了评论数量的统计显示:
然后运行一下我们的项目,发现评论出现了,但是有些却是html片段:
、
那是因为为了保证页面的安全,都默认不允许直接显示html页面,我们可以和Django一样,管道符号加safe:
<p>{{ v.content|safe }}</p>
然后就是分页了:就2步:首先复制这个置于文件开头:
{% import "ui/home_page.html" as pg %}
接着复制下面的替换静态分页效果:
{{ pg.page(page_data, "home.play") }}
然后运行发现报了下面的错误:
werkzeug.routing.BuildError: Could not build url for endpoint 'home.play' with values ['page']. Did you forget to specify values ['id']?
因为这个页面是比较特殊的,我们需要做一下配置:在ui文件夹下面新建comment_page.html,把home_page.html的页面信息全部拷贝进去,然后添加id参数,以及在第几页添加id=id:
现在修改我们play.html的分页配置:开头变成
{% import "ui/comment_page.html" as pg %}
下面也需要修改:
{{ pg.page(page_data, "home.play", movie.id) }}
就是这样:
然后刷新一下,看一下分页功能是否已经实现了呢!!!还记得我们之前在个人中心没有对个人评论进行配置吗,现在我们就可以配置了!
个人中心评论配置
首先需要修改我们的评论视图:
# 评论记录
@home.route('/comments/<int:page>', methods=["GET"])
@user_login_req
def comments(page=None):
if page is None:
page = 1
# 查询的时候关联标签,采用join来加进去,多表关联用filter,过滤用filter_by
page_data = Comment.query.join(
Movie
).join(
User
).filter(
Movie.id == Comment.movie_id,
User.id == session["user_id"]
).order_by(
Comment.addtime.desc()
).paginate(page=page, per_page=10)
return render_template("home/comments.html", page_data=page_data)
然后就是打开comments.html页面,我们直接复制paly.html页面那里面关于评论的那部分:
然后就是分页了,还是2步:首先复制这个置于文件开头:
{% import "ui/comment_page.html" as pg %}
接着复制下面的替换静态分页效果:
{{ pg.page(page_data, "home.comments") }}
然后刷新一下,看看个人中心的评论记录是否都已经显示了呢!!!
电影收藏
使用到的内容
我们将使用到的内容有:
模型:Movie User Moviecol
表单: 无
请求方法: GET
访问控制: 需要登录
1、新定义一个添加收藏函数:
# 添加收藏电影
@home.route('/moviecol/add/', methods=["GET"])
@user_login_req
def moviecol_add():
mid = request.args.get("mid", "")
uid = request.args.get("uid", "")
moviecol = MovieCol.query.filter_by(
user_id=int(uid),
movie_id=int(mid),
).count()
if moviecol == 1:
data = dict(ok=0)
if moviecol == 0:
moviecol = MovieCol(
user_id=int(uid),
movie_id=int(mid),
)
db.session.add(moviecol)
db.session.commit()
data = dict(ok=1)
import json
return json.dumps(data)
2、采用ajax进行收藏的提示
打开play.html页面,我们新定义一个Script,编写我们的ajax代码:
<script>
$(document).ready(function () {
$("#btn-col").click(function () {
var mid = {{ movie.id }};
var uid = {{ session['user_id'] }};
$.ajax({
url: "{{ url_for('home.moviecol_add') }}",
type: "GET",
data: "mid=" + mid + "&uid=" + uid,
dataType: "json",
success: function (res) {
if (res.ok == 1) {
$("#show_col_msg").empty();
$("#show_col_msg").append("收藏成功!");
} else {
$("#show_col_msg").empty();
$("#show_col_msg").append("已经收藏!");
}
}
})
});
});
</script>
3、添加页面收藏提示
继续在我们的play.html页面配置:
然后就可以去测试我们的电影收藏功能是否已经实现了呢,接下来就是会员中心收藏电影的一个显示了,这个和我们的评论记录的显示几乎一样,所以我快点配置。
个人中心电影收藏显示
首先我们需要在menu.html页面配置收藏电影的page=1:
接着去完善我们的收藏电影moviecol,我们可以借鉴之前的会员登入日志的配置:
# 收藏电影
@home.route('/moviecol/<int:page>/', methods=["GET"])
@user_login_req
def moviecol(page=None):
if page is None:
page = 1
# 查询的时候关联标签,采用join来加进去,多表关联用filter,过滤用filter_by
page_data = MovieCol.query.join(
Movie
).join(
User
).filter(
User.id == session["user_id"],
Movie.id == MovieCol.movie_id
).order_by(
MovieCol.addtime.desc()
).paginate(page=page, per_page=10)
return render_template("home/moviecol.html", page_data=page_data)
然后打开moviecol.html页面,我们进行收藏电影的显示:
可能会遗漏page=1
和id=v.movie_id
,但是页面运行时会提示你的,这个按照提示进行即可。
然后就是分页了:还是2步:首先复制这个置于文件开头(可以借鉴我们loginlog.html的配置):
{% import "ui/home_page.html" as pg %}
接着复制下面的替换静态分页效果:
{{ pg.page(page_data, "home.moviecol") }}
然后刷新一下,看看个人中心收藏的电影是否都已经显示了呢!!!
至此,本篇关于上映预告,标签筛选,电影搜索,电影播放,评论显示和收藏电影等功能的介绍就到此为止了。也就是说我们整个项目的开发就全部完成了,后面就是代码的优化和电影弹幕的实现了,我们下一篇介绍了,感谢你的赏阅!!!
本篇笔记对应上传的仓库为:https://github.com/licheetools/movie对应第十四篇。