上映预告

  1. 模型: Preview
  2. 表单: 无
  3. 请求方法: GET
  4. 访问控制: 无

views中进行业务逻辑的实现

@home.route("/animation/")
def animation():"""首页轮播动画"""data = Preview.query.all()return render_template("home/animation.html", data=data)

标签筛选 - 电影分页

  1. 模型: Tag Movie
  2. 表单: 无
  3. 请求方法: GET
  4. 访问控制: 无

编写首页的views

@home.route("/<int:page>/", methods=["GET"])
@home.route("/", methods=["GET"])
def index(page=None):"""首页电影列表"""tags = Tag.query.all()page_data = Movie.query# 标签tid = request.args.get("tid", 0)if int(tid) != 0:page_data = page_data.filter_by(tag_id=int(tid))# 星级star = request.args.get("star", 0)if int(star) != 0:page_data = page_data.filter_by(star=int(star))# 时间time = request.args.get("time", 0)if int(time) != 0:if int(time) == 1:page_data = page_data.order_by(Movie.addtime.desc())else:page_data = page_data.order_by(Movie.addtime.asc())# 播放量pm = request.args.get("pm", 0)if int(pm) != 0:if int(pm) == 1:page_data = page_data.order_by(Movie.playnum.desc())else:page_data = page_data.order_by(Movie.playnum.asc())# 评论量cm = request.args.get("cm", 0)if int(cm) != 0:if int(cm) == 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 = 1page_data = page_data.paginate(page=page, per_page=8)p = dict(tid=tid,star=star,time=time,pm=pm,cm=cm,)return render_template("home/index.html",tags=tags,p=p,page_data=page_data)

电影标签,电影星级,上映时间,播放数量,评论数量

  • tid = request.args.get("tid", 0) 获取到问号传参中的tid没有获取到时置零
  • 同理获取starstar = request.args.get("star", 0)
  • time = request.args.get("time", 0)同理获取到time
  • 其他同理pm cm 这里的数量排序通过前台传过来是0还是1决定数量正序或倒序

碎碎念杂谈,将用户已选择的分类细节展示给用户,可以点击x去除。

mark

可以使用jquery实现,清除组合的时候移除dom节点,显示的时候添加dom节点,然后在添加和清除的时候注意参数的添加和删除,组装成url,通过触发事件触发搜素!

查询出所有的tag,然后经模板渲染出菜单。

tags = Tag.query.all()

传递到模板进行填充。

mark

p = dict(tid=tid,star=star,time=time,pm=pm,cm=cm,)

构建一个参数的字典。

mark

处理标签的链接

 href="{{ url_for('home.index') }}?tid={{ v.id }}&star={{ p['star'] }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm={{ p['cm'] }}"

上面为标签添加href值。其中的tid是取自当前循环

 href="{{ url_for('home.index') }}?tid={{ p['tid'] }}&star={{ v.star }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm={{ p['cm'] }}"

上面为star添加href值。其中的star是取自当前循环

其他项同理可得,将当前值取实际值,其他值取p['']

分页电影

    if int(tid) != 0:page_data = page_data.filter_by(tag_id=int(tid))

其他字段做相同的过滤操作。

进行分页效果展示。

mark

为所有的标签分类添加page=1

mark

电影搜索,搜索分页

  1. 模型: Movie
  2. 表单: 无
  3. 请求方法: GET
  4. 访问控制: 无

views中书写search相关的逻辑处理

@home.route("/search/<int:page>/")
def search(page=None):"""搜索"""if page is None:page = 1key = request.args.get("key", "")movie_count = Movie.query.filter(Movie.title.ilike('%' + key + '%')).count()page_data = Movie.query.filter(Movie.title.ilike('%' + key + '%')).order_by(Movie.addtime.desc()).paginate(page=page, per_page=10)page_data.key = keyreturn render_template("home/search.html", movie_count=movie_count, key=key, page_data=page_data)

mark

为layout中的搜索框添加id

添加id = do_search

mark

mark

home页面中script标签中使用jQuery获取搜索框内key值。然后location跳转到search路由,并携带page key 参数

将这段代码再粘贴到其他需要搜索的页面

  • layout home 都需要修改id

ilike进行模糊匹配

在search页面进行最终结果的填充与分页。

又是这种重复的填充操作,自己瞎做吧。跟以前没什么两样。

新建一个s_page.html,把home_page复制过去就行。

然后依然万年不变import 调用page方法。

碎碎念积累,回车直接搜索:

$("...").keydown(function(e){
if(e.keyCode==13){//处理事件
}
});

电影详情 电影播放 电影评论 电影收藏

  1. 模型: Movie
  2. 表单: 无
  3. 请求方法: GET
  4. 访问控制: 无

评论统计:

  1. 模型: Movie User Comment
  2. 表单: CommentForm
  3. 请求方法: GET POST
  4. 访问控制: 需登录

mark

如果当前未登录则显示请先登录才可以提交。

mark

只有用户登录状态才会显示评论框。

forms中添加commentsform

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"})

注意内容的id input_content

views中处理播放页面的数据业务逻辑,以及评论的业务逻辑

@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 = 1page_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 + 1form = CommentForm()# 必须登录if "user" in session and form.validate_on_submit():data = form.datacomment = Comment(content=data["content"],movie_id=movie.id,user_id=session["user_id"])db.session.add(comment)db.session.commit()movie.commentnum = movie.commentnum + 1db.session.add(movie)db.session.commit()flash("添加评论成功!", "ok")return redirect(url_for('home.play', id=movie.id, page=1))db.session.add(movie)db.session.commit()return render_template("home/play.html", movie=movie, form=form, page_data=page_data)

index以及search页面中的播放按钮,都添加上v.id 以及page

前往play中填充movie的具体数据。使用form填充评论框,使用pagedata填充已有评论

  • 当然flash的位置,报错信息。submit之前的csrf都不要忘记,还有form的method

mark

修改js中需要修改的player file title 等

为评论分页新建一个html ui/comment_page.html复制s_page的内容

为commentspage添加id参数。url中也添加id

然后又是重复的引入和page方法调用。pagedata填充

为了安全,默认不会显示html的内容,添加safe

mark

查询出自己的评论记录显示在自己个人中心

@home.route("/comments/<int:page>/")
@user_login_req
def comments(page=None):"""个人中心评论记录"""if page is None:page = 1page_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进行pagedata填充以及分页处理。

menu中评论记录url添加page=1

mark

收藏电影

  1. 模型: Movie User Moviecol
  2. 表单: 无
  3. 请求方法: GET
  4. 访问控制: 需登录

通过ajax异步方法添加电影收藏。

mark

ajax的提示信息无处安放,添加上图id 为show_col_msg

play页面中有一个按钮是收藏电影,id为btn-col

mark

为btn-col 设置点击事件,获取当前的movieid,获取当前的用户。
使用ajax,提交的地址。type:get,提交的数据,返回的数据类型json。
成功之后的处理函数res接收返回的json对象

@home.route("/moviecol/add/", methods=["GET"])
@user_login_req
def moviecol_add():"""添加电影收藏"""uid = request.args.get("uid", "")mid = request.args.get("mid", "")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 jsonreturn json.dumps(data)

处理个人中心中电影收藏的view

@home.route("/moviecol/<int:page>/")
@user_login_req
def moviecol(page=None):"""电影收藏"""if page is None:page = 1page_data = Moviecol.query.join(Movie).join(User).filter(Movie.id == Moviecol.movie_id,User.id == session["user_id"]).order_by(Moviecol.addtime.desc()).paginate(page=page, per_page=10)return render_template("home/moviecol.html", page_data=page_data)

page_data进行填充,进行分页

menus中将收藏电影

mark

mark

修改这里配置菜单显示哪些按钮。

  • 换不存在的账号登录出现报错
builtins.AttributeError
AttributeError: 'NoneType' object has no attribute 'check_pwd'

解决方案:

        user = User.query.filter_by(name=data["name"]).first()if user:if not user.check_pwd(data["pwd"]):flash("密码错误!", "err")return redirect(url_for("home.login"))else:flash("账户不存在!", "err")return redirect(url_for("home.login"))

FLask 结合Redis消息队列实现电影弹幕

  1. 模型: Movie
  2. 表单: 无
  3. 请求方法: GET POST
  4. 访问控制: 无
  5. 消息队列: Redis
  6. Flask第三方扩展: Flask-Redis
  7. 弹幕播放器插件: dplayer.js(开源)

redis自行前往官网下载最新稳定版本

pip install flask-redis

前面的版本使用的是jwplayer

yum -y install gcc gcc-c++
tar zxf redis-4.0.1.tar.gz
cd redis-4.0.1/

可以看到当前目录有Makefile文件,安装。

make && make install

启动服务

./utils/install_server.sh
vim /etc/redis/6379.conf

修改bind的地址

redis-cli -h 192.x.x.x

弹幕播放器views实现

@home.route("/video/<int:id>/<int:page>/", methods=["GET", "POST"])
def video(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 = 1page_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 + 1form = CommentForm()if "user" in session and form.validate_on_submit():data = form.datacomment = Comment(content=data["content"],movie_id=movie.id,user_id=session["user_id"])db.session.add(comment)db.session.commit()movie.commentnum = movie.commentnum + 1db.session.add(movie)db.session.commit()flash("添加评论成功!", "ok")return redirect(url_for('home.video', id=movie.id, page=1))db.session.add(movie)db.session.commit()return render_template("home/video.html", movie=movie, form=form, page_data=page_data)

templates目录创建一个video.html把原本play中的代码粘贴过来

将原本的jwplayer部分的script可以直接全部去掉了

mark

将评论这里的分页中视图改为video

将jwplayer的css去掉

进入播放需要的静态资源

<link rel="stylesheet" href="{{ url_for('static',filename='dplayer/dist/DPlayer.min.css') }}">
<script src="{{ url_for('static',filename='dplayer/plugin/flv.min.js') }}"></script>
<script src="{{ url_for('static',filename='dplayer/plugin/hls.min.js') }}"></script>
<script src="{{ url_for('static',filename='dplayer/dist/DPlayer.min.js') }}"></script>

修改样式

    .dplayer-comment-setting-type>label{display: inline;

定义播放器的样式

        <div id="dplayer1" style="height:500px;width: 774px;"></div>

播放页面

<script>var dp1 = new DPlayer({element: document.getElementById('dplayer1'),video: {url: "{{ url_for('static',filename='uploads/'+movie.url) }}",},danmaku: {id: '{{ movie.id }}',api: "/tm/"}});
</script>

在官方网站的demo上开发者工具xhr可以看到弹幕发送及加载数据的接口。

发送的格式是json的字符串。

定义弹幕相关的处理方法

init文件中

from flask_redis import FlaskRedis

定义我们redis的url格式

app.config["REDIS_URL"] = "redis://127.0.0.1:6379/0"
rd = FlaskRedis(app)

views.py中引入

@home.route("/tm/", methods=["GET", "POST"])
def tm():"""弹幕消息处理"""import jsonif request.method == "GET":# 获取弹幕消息队列id = request.args.get('id')# 存放在redis队列中的键值key = "movie" + str(id)if rd.llen(key):msgs = rd.lrange(key, 0, 2999)res = {"code": 1,"danmaku": [json.loads(v) for v in msgs]}else:res = {"code": 1,"danmaku": []}resp = json.dumps(res)if request.method == "POST":# 添加弹幕data = json.loads(request.get_data())msg = {"__v": 0,"author": data["author"],"time": data["time"],"text": data["text"],"color": data["color"],"type": data['type'],"ip": request.remote_addr,"_id": datetime.datetime.now().strftime("%Y%m%d%H%M%S") + uuid.uuid4().hex,"player": [data["player"]]}res = {"code": 1,"data": msg}resp = json.dumps(res)# 将添加的弹幕推入redis的队列中rd.lpush("movie" + str(data["player"]), json.dumps(msg))return Response(resp, mimetype='application/json')

原理:

mark

代码优化及bug处理

  1. 头像判断
  2. 关键字搜索分页
  3. 电影右侧播放页面滚动条
builtins.TypeError
TypeError: must be str, not NoneType

mark

如果有头像,显示头像,没有头像就显示holder的空头像。

评论记录中的头像部分做相同处理

后台的会员列表也做同样的处理

mark

后台的评论列表也做同样的处理

mark

mark

会员详情中的会员头像也要判断templates/admin/user_view.html

mark

关键字搜索分页

搜索分页中当前key会丢失掉

mark

spage中的key要传递进去。

当影片内容过长设置滚动条

mark

play 和 video中都做同样处理

17 -Flask构建弹幕微电影网站- 电影播放及评论弹幕收藏实现相关推荐

  1. 【Python-Microfilm-web-app-flask】基于Flask构建的微电影网站实例及源码参考

    前言 2019年5月20号,系统集成项目工程师考试结束,这个意味这今年的目标实现了一小部分,毕竟是一年多没有再参加考试,这次考试,又体会到了头脑风暴,考试这种活动,和编程不是一个层次.编程我可以有N种 ...

  2. (旧)3- Flask构建弹幕微电影网站- 课程介绍

    Flask 构建微电影视频网站 已上线演示地址: http://movie.mtianyan.cn 项目源码地址:https://github.com/mtianyan/movie_project 持 ...

  3. (旧)2- 大家一起学:Flask构建弹幕微电影网站-前端首页搭建-0

    Flask 构建微电影视频网站 已上线演示地址: http://movie.mtianyan.cn 项目源码地址:https://github.com/mtianyan/movie_project 上 ...

  4. 弹幕 mysql_3、Flask构建弹幕微电影网站-安装mysql数据库及配置

    Flask 构建微电影视频网站 安装数据库连接依赖包 安装包flask-sqlalchemy pip install flask-sqlalchemy pip list Package Version ...

  5. 18 -Flask构建弹幕微电影网站- 部署上线

    Centos7(博主使用的是ubuntu) 数据库: mysql 编程语言: python3.6 队列缓存: redis web反向代理: nginx 依赖环境: flask pymysqlclien ...

  6. 用python开发一个影视网站_GitHub - lyzhanghai/movie_project: 一个使用Python+Flask开发的微电影网站...

    微电影网站搭建手册 简介 这是一个使用Python语言和Flask框架搭建的微电影网站.网站分前台和后台,前台面向用户,主要功能有注册会员.搜索电影.观看电影.收藏及评论电影:后台面向网站管理人员,主 ...

  7. 15 -Flask构建弹幕微电影网站-基于角色的访问控制

    本章内容: 基于角色的访问控制 已上线演示地址: http://movie.mtianyan.cn 项目源码地址:https://github.com/mtianyan/movie_project 基 ...

  8. (新的开始)4- Flask构建弹幕微电影网站-环境搭建

    已上线演示地址: http://movie.mtianyan.cn 项目源码地址:https://github.com/mtianyan/movie_project 准备开发环境 windows环境搭 ...

  9. flask学习:开发一个微电影网站一:项目介绍

    最近在学习flask,完成了入门学习,现在想找一个项目进行实战学习,看看系统的开发是怎么样的,然后看到了慕课网上有一个视频,使用flask开发一个微电影网站,因此决定花时间学习一下. 一:首先介绍一下 ...

最新文章

  1. 拯救老电影——详解爱奇艺ZoomAI视频增强技术的应用
  2. YYCache 源码学习(一):YYMemoryCache
  3. struts2文件上传大小限制问题小结(引用)
  4. pragma指令简介
  5. HTML5/CSS3系列教程:使用SVG图片
  6. Tcp方式采集CNC兄弟设备数据
  7. C语言递归实现深度优先搜索DFS算法(附完整源码)
  8. 编写你的第一个 Django 应用,第 4 部分
  9. python 进程间通信(上)
  10. Java泛型,枚举,注解
  11. 金山云发布全新Serverless产品 云原生基础设施再升级
  12. dedecms 5.7 站点文件从本地子目录上传到远程根目录后找不到模板的解决方案
  13. 获取元素在文档上的正确坐标
  14. 19. 网购秒杀系统架构分析
  15. python数据类型有哪些、分别有什么用途_python数据类型
  16. C4996: 'inet_addr': Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS
  17. 技术人生:恶补基础知识
  18. android微信刷脸支付,安卓首发 Find X支持微信人脸支付功能
  19. Spring:ReflectionUtils工具类使用一:Field
  20. 主体阶段钢筋工程、模板工程、混凝土、管线预埋施工要点都有哪些?

热门文章

  1. DEEPIN 安装软件的方法
  2. 102页PPT!阿里巴巴数字智能工厂解决方案
  3. oracle 创建 temporary tablespace group
  4. 服务器连接不上可能是哪些原因
  5. 编程会像手机拍照一样傻瓜
  6. GWAS理论 1-4 关联分析模型和常用软件介绍
  7. 昨天去做地推,在路上看见了这么繁茂的仙人掌
  8. 【进制】计算机底层是如何计算2+3的?
  9. ya的意思_请问ya是你的意思吗,为什么不写成yo – 手机爱问
  10. SOLIDWORKS会遇到的预览问题