頁面完成後的最終佈局css
電影視頻網站首頁面html
會員登陸頁面前端
會員註冊頁面jquery
點擊退出和會員按鈕,直接進入會員登陸頁面web
視頻播放頁面數據庫
能夠看到,頁面共同的部分是頂部導航和底部導航flask
因此咱們能夠把頁面頂部導航和底部導航部分單獨定義一個文件home.html,而後讓須要使用頂部導航和底部導航的頁面都繼承home.html頁面bootstrap
在templates目錄的home目錄下建立home.html頁面
,用來定義頁面頂部導航和底部導航部分
session
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1 , user-scalable=no"> <title>微電影</title> <link rel="shortcut icon" href="{{ url_for('static',filename='base/images/logo.png') }}"> <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap.min.css') }}"> <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap-movie.css') }}"> <link rel="stylesheet" href="{{ url_for('static',filename='base/css/animate.css') }}"> <style> .navbar-brand > img { display: inline; } .media { padding: 3px; border: 1px solid #ccc } </style> </head> {% block css %} {% endblock %} <body> <!--導航--> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <!--小屏幕導航按鈕和logo--> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="{{ url_for('home.index',page=1) }}" class="navbar-brand" style="width:250px;"> <img src="{{ url_for('static',filename='base/images/logo.png') }}" style="height:30px;"> 微電影 </a> </div> <!--小屏幕導航按鈕和logo--> <!--導航--> <div class="navbar-collapse collapse"> <form class="navbar-form navbar-left" role="search" style="margin-top:18px;"> <div class="form-group input-group"> <input type="text" class="form-control" placeholder="請輸入電影名!"> <span class="input-group-btn"> <a class="btn btn-default" id='do-search'><span class="glyphicon glyphicon-search"></span> 搜索</a> </span> </div> </form> <ul class="nav navbar-nav navbar-right"> <li> <a class="curlink" href="{{ url_for('home.index',page=1) }}"><span class="glyphicon glyphicon-film"></span> 電影</a> </li> <li> <a class="curlink" href="{{ url_for('home.login') }}"><span class="glyphicon glyphicon-log-in"></span> 登陸</a> </li> <li> <a class="curlink" href="{{ url_for('home.register') }}"><span class="glyphicon glyphicon-plus"></span> 註冊</a> </li> <li> <a class="curlink" href="{{ url_for('home.logout') }}"><span class="glyphicon glyphicon-log-out"></span> 退出</a> </li> <li> <a class="curlink" href="{{ url_for('home.user') }}"><span class="glyphicon glyphicon-user"></span> 會員</a> </li> </ul> </div> <!--導航--> </div> </nav> <!--導航--> <!--內容--> <div class="container" style="margin-top:76px"> {% block content %} {% endblock %} </div> <!--內容--> <!--底部--> <footer> <div class="container"> <div class="row"> <div class="col-md-12"> <p> © 2017 flaskmovie.com 京ICP備 123456789號 </p> </div> </div> </div> </footer> <!--底部--> <script src="{{ url_for('static',filename='base/js/jquery.min.js') }}"></script> <script src="{{ url_for('static',filename='base/js/bootstrap.min.js') }}"></script> <script src="{{ url_for('static',filename='base/js/jquery.singlePageNav.min.js') }}"></script> <script src="{{ url_for('static',filename='base/js/wow.min.js') }}"></script> <script src="{{ url_for('static',filename='lazyload/jquery.lazyload.min.js') }}"></script> <script src="//cdn.bootcss.com/holder/2.9.4/holder.min.js"></script> <script> $(function () { new WOW().init(); }) </script> <script> $(document).ready(function () { $("img.lazy").lazyload({ effect: "fadeIn" }); $("#do_search").click(function () { var key = $("#key_movie").val(); location.href = "{{ url_for('home.search',page=1) }}?key=" + key; }); }); </script> {% block js %} {% endblock %} </body> </html>
在home目錄下建立forms.py文件,用來定義登陸的表單LoginFormapp
能夠經過調用LoginForm表單類直接在前端頁面上渲染生成登陸須要的字段標籤
from flask_wtf import FlaskForm from wtforms.fields import StringField, PasswordField, SubmitField, FileField, TextAreaField from wtforms.validators import DataRequired, EqualTo, Email, Regexp, ValidationError from app.models import User class LoginForm(FlaskForm): name = StringField( label="帳號", validators=[ DataRequired("請輸入賬號!") ], description="帳號", render_kw={ "class": "form-control input-lg", "placeholder": "請輸入賬號!" } ) pwd = PasswordField( label="密碼", validators=[ DataRequired("請輸入密碼!") ], description="密碼", render_kw={ "class": "form-control input-lg", "placeholder": "請輸入密碼!", } ) submit = SubmitField( "登陸", render_kw={ "class": "btn btn-lg btn-primary btn-block" } ) def validate_name(self, field): name = field.data user = User.query.filter_by(name=name).count() if user == 0: raise ValidationError("會員帳號不存在!") def validata_pwd(self, field): from app.models import User pwd = field.data name = self.name.data user = User.query.filter_by(name=name).count() if not user.check_pwd(pwd): raise ValidationError("密碼錯誤!")
@home.route("/login/", methods=['GET', 'POST']) def login(): form = LoginForm() if form.validate_on_submit(): # 若是用戶輸入的用戶名和密碼符合驗證條件 data = form.data # 獲取用戶輸入的表單數據 user = User.query.filter_by(name=data.get("name")).first() # 根據用戶名查詢數據庫,返回第一個查詢結果 if user == None: # 若是從數據庫中查不到用戶名 flash("會員帳號不存在,請從新輸入!", "err") return redirect(url_for("home.login")) elif not user.check_pwd(data.get("pwd")): # 若是從數據庫查詢到用戶名但密碼不匹配 flash("用戶名或密碼錯誤!", "err") return redirect(url_for("home.login")) session['user'] = user.name # 定義session信息 session['user_id'] = user.id userlog = Userlog( # 定義用戶登陸日誌 user_id=user.id, ip=request.remote_addr ) db.session.add(userlog) # 添加用戶登陸日誌 db.session.commit() return redirect(url_for("home.user")) return render_template("home/login.html", form=form)
{% extends "home/home.html" %} {% block content %} <div class="row"> <div class="col-md-4 col-md-offset-4"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title"><span class="glyphicon glyphicon-log-in"></span> 會員登陸</h3> </div> <div class="panel-body"> <!--消息閃現--> {% for msg in get_flashed_messages(category_filter=["err"]) %} <p style="color:red">{{ msg }}</p> {% endfor %} {% for msg in get_flashed_messages(category_filter=["ok"]) %} <p style="color:green">{{ msg }}</p> {% endfor %} <form role="form" method="post"> <fieldset> <div class="form-group"> <label for="input_contact"><span class="glyphicon glyphicon-user"></span> {{ form.name.label }}</label> {{ form.name }} </div> <!--錯誤提示--> {% for err in form.name.errors %} <div class="col-md-12"> <font style="color:red">{{ err }}</font> </div> {% endfor %} <div class="form-group"> <label for="input_password"><span class="glyphicon glyphicon-lock"></span> {{ form.pwd.label }}</label> {{ form.pwd }} </div> <!--錯誤提示--> {% for err in form.pwd.errors %} <div class="col-md-12"> <font style="color:red">{{ err }}</font> </div> {% endfor %} {{ form.csrf_token }} {{ form.submit }} </fieldset> </form> </div> </div> </div> </div> {% endblock %}
@home.route("/logout/") def logout(): session.pop("user", None) # 從session中刪除用戶名 session.pop("user_id", None) # 從session中刪除用戶id return redirect(url_for("home.login"))
<!doctype html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1 , user-scalable=no"> <title>微電影</title> <link rel="shortcut icon" href="{{ url_for('static',filename='base/images/logo.png') }}"> <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap.min.css') }}"> <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap-movie.css') }}"> <link rel="stylesheet" href="{{ url_for('static',filename='base/css/animate.css') }}"> <style> .navbar-brand > img { display: inline; } .media { padding: 3px; border: 1px solid #ccc } </style> {% block css %}{% endblock %} </head> <body> <!--導航--> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <!--小屏幕導航按鈕和logo--> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="{{ url_for('home.index',page=1) }}" class="navbar-brand" style="width:250px;"> <img src="{{ url_for('static',filename='base/images/logo.png') }}" style="height:30px;"> 微電影 </a> </div> <!--小屏幕導航按鈕和logo--> <!--導航--> <div class="navbar-collapse collapse"> <form class="navbar-form navbar-left" role="search" style="margin-top:18px;"> <div class="form-group input-group"> <input type="text" class="form-control" placeholder="請輸入電影名!" id="key_movie"> <span class="input-group-btn"> <a class="btn btn-default" id="do_search"><span class="glyphicon glyphicon-search"></span> 搜索</a> </span> </div> </form> <ul class="nav navbar-nav navbar-right"> <li> <a class="curlink" href="{{ url_for('home.index',page=1) }}"><span class="glyphicon glyphicon-film"></span> 電影</a> </li> <li> <a class="curlink" href="{{ url_for('home.login') }}"><span class="glyphicon glyphicon-log-in"></span> 登陸</a> </li> <li> <a class="curlink" href="{{ url_for('home.regist') }}"><span class="glyphicon glyphicon-plus"></span> 註冊</a> </li> <li> <a class="curlink" href="{{ url_for('home.logout') }}"><span class="glyphicon glyphicon-log-out"></span> 退出</a> </li> <li> <a class="curlink" href="{{ url_for('home.user') }}"><span class="glyphicon glyphicon-user"></span> 會員</a> </li> </ul> </div> <!--導航--> </div> </nav> <!--導航--> <!--內容--> {% block content %} {% endblock %} <!--內容--> <!--底部--> <footer> <div class="container"> <div class="row"> <div class="col-md-12"> <p> © 2017 flaskmovie.com 京ICP備 123456789號 </p> </div> </div> </div> </footer> <!--底部--> <script src="{{ url_for('static',filename='base/js/jquery.min.js') }}"></script> <script src="{{ url_for('static',filename='base/js/bootstrap.min.js') }}"></script> <script src="{{ url_for('static',filename='base/js/jquery.singlePageNav.min.js') }}"></script> <script src="{{ url_for('static',filename='base/js/wow.min.js') }}"></script> <script src="{{ url_for('static',filename='lazyload/jquery.lazyload.min.js') }}"></script> <script src="//cdn.bootcss.com/holder/2.9.4/holder.min.js"></script> <script> $(function () { new WOW().init(); }) </script> <script> $(document).ready(function () { $("img.lazy").lazyload({ effect: "fadeIn" }); $("#do_search").click(function () { var key = $("#key_movie").val(); location.href = "{{ url_for('home.search',page=1) }}?key=" + key; }); }); </script> {% block js %}{% endblock %} </body> </html>
能夠經過調用RegistForm類直接在前端頁面渲染生成註冊使用的字段標籤
from flask_wtf import FlaskForm from wtforms.fields import StringField, PasswordField, SubmitField, FileField, TextAreaField from wtforms.validators import DataRequired, EqualTo, Email, Regexp, ValidationError from app.models import User class RegistForm(FlaskForm): name = StringField( label="呢稱", validators=[ DataRequired("請輸入呢稱!") ], description="呢稱", render_kw={ "class": "form-control input-lg", "placeholder": "請輸入呢稱!", } ) email = StringField( label="郵箱", validators=[ DataRequired("請輸入郵箱!"), Email("郵箱格式不正確!"), ], description="郵箱", render_kw={ "class": "form-control input-lg", "placeholder": "請輸入郵箱!" } ) phone = StringField( label="手機號", validators=[ DataRequired("請輸入手機號!"), Regexp("1[34578]\\d{9}", message="輸入的手機號格式不正確!"), ], description="手機號", render_kw={ "class": "form-control input-lg", "placeholder": "請輸入手機號!" } ) pwd = PasswordField( label="密碼", validators=[ DataRequired("請輸入密碼!") ], description="密碼", render_kw={ "class": "form-control input-lg", "placeholder": "請輸入密碼!" } ) repwd = PasswordField( label="確認密碼", validators=[ DataRequired("請輸入確認密碼!"), EqualTo("pwd", message="兩次密碼不一致!") ], description="確認密碼", render_kw={ "class": "form-control input-lg", "placeholder": "請輸入確認密碼!" } ) submit = SubmitField( "註冊", render_kw={ "class": "btn btn-lg btn-success btn-block" } ) def validate_name(self, field): name = field.data user = User.query.filter_by(name=name).count() if user == 1: raise ValidationError("呢稱已經存在,請從新輸入!") def validate_email(self, field): email = field.data user = User.query.filter_by(email=email).count() if user == 1: raise ValidationError("郵箱已經存在,請從新輸入!") def validate_phone(self, field): phone = field.data user = User.query.filter_by(phone=phone).count() if user == 1: raise ValidationError("手機號已經存在,請從新輸入!")
@home.route("/register/", methods=["GET", "POST"]) def register(): form = RegistForm() # 獲取用戶輸入的註冊信息數據 if form.validate_on_submit(): # 若是用戶輸入的註冊數據經過form基礎驗證 data = form.data # 獲取用戶輸入的表單數據 user = User( name=data.get("name"), # 從表單中獲取用戶輸入的用戶名 email=data.get("email"), # 從表單中獲取用戶輸入的郵箱地址 phone=data.get("phone"), # 從表單中獲取用戶輸入的手機號 pwd=generate_password_hash(data.get("pwd")), # 從表單中獲取用戶輸入的密碼並進行加密 uuid=uuid.uuid4().hex # 生成uuid,保證惟一性 ) db.session.add(user) # 添加用戶 db.session.commit() # 向數據庫提交用戶註冊信息 flash("註冊成功!", "ok") return redirect(url_for("home.login")) return render_template("home/register.html", form=form)
{% extends 'home/home.html' %} {% block content %} <div class="row"> <div class="col-md-4 col-md-offset-4"> <div class="panel panel-success"> <div class="panel-heading"> <h3 class="panel-title"><span class="glyphicon glyphicon-plus"></span> 會員註冊</h3> </div> <div class="panel-body"> <!--消息閃現--> {% for msg in get_flashed_messages(category_filter=["err"]) %} <p style="color:red">{{ msg }}</p> {% endfor %} {% for msg in get_flashed_messages(category_filter=["ok"]) %} <p style="color:green">{{ msg }}</p> {% endfor %} <form role="form" method="post"> <fieldset> <div class="form-group"> <label for="input_name"><span class="glyphicon glyphicon-user"></span> {{ form.name.label }}</label> {{ form.name }} </div> <!--錯誤提示--> {% for err in form.name.errors %} <div class="col-md-12"> <font style="color:red">{{ err }}</font> </div> {% endfor %} <div class="form-group"> <label for="input_email"><span class="glyphicon glyphicon-envelope"></span> {{ form.email.label }}</label> {{ form.email }} </div> <!--錯誤提示--> {% for err in form.email.errors %} <div class="col-md-12"> <font style="color:red">{{ err }}</font> </div> {% endfor %} <div class="form-group"> <label for="input_phone"><span class="glyphicon glyphicon-phone"></span> {{ form.phone.label }}</label> {{ form.phone }} </div> <!--錯誤提示--> {% for err in form.phone.errors %} <div class="col-md-12"> <font style="color:red">{{ err }}</font> </div> {% endfor %} <div class="form-group"> <label for="input_password"><span class="glyphicon glyphicon-lock"></span> {{ form.pwd.label }}</label> {{ form.pwd }} </div> <!--錯誤提示--> {% for err in form.pwd.errors %} <div class="col-md-12"> <font style="color:red">{{ err }}</font> </div> {% endfor %} <div class="form-group"> <label for="input_repassword"><span class="glyphicon glyphicon-lock"></span> {{ form.repwd.label }}</label> {{ form.repwd }} </div> <!--錯誤提示--> {% for err in form.repwd.errors %} <div class="col-md-12"> <font style="color:red">{{ err }}</font> </div> {% endfor %} {{ form.submit }} {{ form.csrf_token }} </fieldset> </form> </div> </div> </div> </div> {% endblock %}
@home.route("/<int:page>/", methods=['GET']) def index(page=None): tags = Tag.query.all() # 獲取數據庫中全部的電影標籤 page_data = Movie.query # 從數據庫中獲取全部的電影信息 tid = request.args.get("tid", 0) # 獲取用戶請求的電影標籤id if int(tid) != 0: page_data = page_data.filter_by(tag_id=int(tid)) # 根據用戶請求的頁碼進行過濾 star = request.args.get("star", 0) # 獲取用戶請求的電影星級id if int(star) != 0: page_data = page_data.filter(star=int(star)) # 根據用戶請求的電影星級id進行過濾 time = request.args.get("time", 0) # 獲取用戶請求的電影添加時間 if int(time) != 0: page_data = page_data.order_by(Movie.addtime) # 獲取用戶請求的電影添加時間進行過濾 pm = request.args.get("pm", 0) # 獲取用戶請求的電影播放次數 if int(pm) != 0: page_data = page_data.order_by(Movie.playnum) # 獲取用戶請求的電影播放次數進行過濾 cm = request.args.get("cm", 0) # 獲取用戶請求的電影評論次數 if int(cm) != 0: page_data = page_data.order_by(Movie.commentnum) # 獲取用戶請求的電影評論次數進行過濾 if page is None: # 獲取用戶請求的頁數 page = 1 page_data = page_data.paginate(page=page, per_page=10) # 進行分頁,每頁顯示10條電影數據 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)
{% macro page(data,url) -%} {% if data %} <nav aria-label="Page navigation"> <ul class="pagination"> <li><a href="{{ url_for(url,page=1) }}">首頁</a></li> {% if data.has_prev %} <li><a href="{{ url_for(url,page=data.prev_num) }}">上一頁</a></li> {% else %} <li class="disabled"><a href="#">上一頁</li> {% endif %} {% for v in data.iter_pages() %} {% if v == data.page %} <li class="active"><a href="#">{{ v }}</a></li> {% else %} <li><a href="{{ url_for(url,page=v) }}">{{ v }}</a></li> {% endif %} {% endfor %} {% if data.has_next %} <li><a href="{{ url_for(url,page=data.next_num) }}">下一頁</a></li> {% else %} <li class="disabled"><a href="#">下一頁</a></li> {% endif %} <li><a href="{{ url_for(url,page=data.pages) }}">尾頁</a></li> </ul> </nav> {% endif %} {%- endmacro %}
{% extends "home/layout.html" %} {% import "ui/home_page.html" as pg %} {% block content %} <!--熱門電影--> <section id="hotmovie" style="margin-top:76px"> <div class="container"> <div class="row wow fadeInRight" data-wow-delay="0.6s"> <div class="row"> <iframe class="wow fadeIn" width="100%" height="375px" frameborder=0 scrolling=no src="{{ url_for('home.animation') }}"></iframe> </div> </div> </div> </section> <!--熱門電影--> <!--電影列表--> <section id="movielist"> <div class="container"> <div class="row wow fadeIn" data-wow-delay="0.6s"> <div class="col-md-12 table-responsive"> <table class="table text-left table-bordered" id="movietags"> <tr> <td style="width:10%;">電影標籤</td> <td style="width:90%;"> {% for v in tags %} <a href="{{ url_for('home.index',page=1) }}?tid={{ v.id }}&star={{ p['star'] }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm={{ p['cm'] }}" class="label label-info"><span class="glyphicon glyphicon-tag"></span> {{ v.name }}</a> {% endfor %} </tr> <tr> <td>電影星級</td> <td> {% for v in range(1,6) %} <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ v }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm={{ p['cm'] }}" class="label label-warning"><span class="glyphicon glyphicon-star"></span> {{ v }}星</a> {% endfor %} </td> </tr> <tr> <td>上映時間</td> <td> <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time=1&pm={{ p['pm'] }}&cm={{ p['cm'] }}" class="label label-default"><span class="glyphicon glyphicon-time"></span> 最近</span></a> <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time=2&pm={{ p['pm'] }}&cm={{ p['cm'] }}" class="label label-default"><span class="glyphicon glyphicon-time"></span> 更早</span></a> </td> </tr> <tr> <td>播放數量</td> <td> <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm=1&cm={{ p['cm'] }}" class="label label-success"><span class="glyphicon glyphicon-arrow-down"></span> 從高到底</span> </a> <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm=2&cm={{ p['cm'] }}" class="label label-danger"><span class="glyphicon glyphicon-arrow-up"></span> 從低到高</span> </a> </td> </tr> <tr> <td>評論數量</td> <td> <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm=1" class="label label-success"><span class="glyphicon glyphicon-arrow-down"></span> 從高到底</span> </a> <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm=2" class="label label-danger"><span class="glyphicon glyphicon-arrow-up"></span> 從低到高</span> </a> </td> </tr> </table> </div> {% for v in page_data.items %} <div class="col-md-3"> <div class="movielist text-center"> <img src="{{ url_for('static',filename='uploads/'+v.logo) }}" class="img-responsive center-block" alt=""> <div class="text-left" style="margin-left:auto;margin-right:auto;width:210px;"> <span style="color:#999;font-style: italic;">{{ v.title }}</span><br> <div> {% for val in range(1,v.star+1) %} <span class="glyphicon glyphicon-star" style="color:#FFD119"></span> {% endfor %} {% for val in range(1,6-v.star) %} <span class="glyphicon glyphicon-star-empty" style="color:#FFD119"></span> {% endfor %} </div> </div> <a href="{{ url_for('home.play',id=v.id,page=1) }}" class="btn btn-primary" target="_blank" role="button"><span class="glyphicon glyphicon-play"></span> 播放</a> </div> </div> {% endfor %} <div class="col-md-12"> {{ pg.page(page_data,'home.index') }} </div> </div> </div> </section> <!--電影列表--> {% endblock %}
至此,電影網站的首頁面開發完成了