页面完成后的最终布局

电影视频网站首页面

会员登录页面

会员注册页面

点击退出和会员按钮,直接进入会员登录页面

视频播放页面

可以看到,页面共同的部分是顶部导航和底部导航

所以我们可以把页面顶部导航和底部导航部分单独定义一个文件home.html,然后让需要使用顶部导航和底部导航的页面都继承home.html页面

1.创建父模板home.html

在templates目录的home目录下创建home.html页面,用来定义页面顶部导航和底部导航部分

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="renderer" content="webkit">
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8. <meta name="viewport" content="width=device-width, initial-scale=1 , user-scalable=no">
  9. <title>微电影</title>
  10. <link rel="shortcut icon" href="{{ url_for('static',filename='base/images/logo.png') }}">
  11. <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap.min.css') }}">
  12. <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap-movie.css') }}">
  13. <link rel="stylesheet" href="{{ url_for('static',filename='base/css/animate.css') }}">
  14. <style>
  15. .navbar-brand > img {
  16. display: inline;
  17. }
  18. .media {
  19. padding: 3px;
  20. border: 1px solid #ccc
  21. }
  22. </style>
  23. </head>
  24. {% block css %}
  25. {% endblock %}
  26. <body>
  27. <!--导航-->
  28. <nav class="navbar navbar-default navbar-fixed-top">
  29. <div class="container">
  30. <!--小屏幕导航按钮和logo-->
  31. <div class="navbar-header">
  32. <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
  33. <span class="icon-bar"></span>
  34. <span class="icon-bar"></span>
  35. <span class="icon-bar"></span>
  36. </button>
  37. <a href="{{ url_for('home.index',page=1) }}" class="navbar-brand" style="width:250px;">
  38. <img src="{{ url_for('static',filename='base/images/logo.png') }}" style="height:30px;">&nbsp;微电影
  39. </a>
  40. </div>
  41. <!--小屏幕导航按钮和logo-->
  42. <!--导航-->
  43. <div class="navbar-collapse collapse">
  44. <form class="navbar-form navbar-left" role="search" style="margin-top:18px;">
  45. <div class="form-group input-group">
  46. <input type="text" class="form-control" placeholder="请输入电影名!">
  47. <span class="input-group-btn">
  48. <a class="btn btn-default" id='do-search'><span
  49. class="glyphicon glyphicon-search"></span>&nbsp;搜索</a>
  50. </span>
  51. </div>
  52. </form>
  53. <ul class="nav navbar-nav navbar-right">
  54. <li>
  55. <a class="curlink" href="{{ url_for('home.index',page=1) }}"><span
  56. class="glyphicon glyphicon-film"></span>&nbsp;电影</a>
  57. </li>
  58. <li>
  59. <a class="curlink" href="{{ url_for('home.login') }}"><span
  60. class="glyphicon glyphicon-log-in"></span>&nbsp;登录</a>
  61. </li>
  62. <li>
  63. <a class="curlink" href="{{ url_for('home.register') }}"><span
  64. class="glyphicon glyphicon-plus"></span>&nbsp;注册</a>
  65. </li>
  66. <li>
  67. <a class="curlink" href="{{ url_for('home.logout') }}"><span
  68. class="glyphicon glyphicon-log-out"></span>&nbsp;退出</a>
  69. </li>
  70. <li>
  71. <a class="curlink" href="{{ url_for('home.user') }}"><span class="glyphicon glyphicon-user"></span>&nbsp;会员</a>
  72. </li>
  73. </ul>
  74. </div>
  75. <!--导航-->
  76. </div>
  77. </nav>
  78. <!--导航-->
  79. <!--内容-->
  80. <div class="container" style="margin-top:76px">
  81. {% block content %}
  82. {% endblock %}
  83. </div>
  84. <!--内容-->
  85. <!--底部-->
  86. <footer>
  87. <div class="container">
  88. <div class="row">
  89. <div class="col-md-12">
  90. <p>
  91. ©&nbsp;2017&nbsp;flaskmovie.com&nbsp;京ICP备 123456789号
  92. </p>
  93. </div>
  94. </div>
  95. </div>
  96. </footer>
  97. <!--底部-->
  98. <script src="{{ url_for('static',filename='base/js/jquery.min.js') }}"></script>
  99. <script src="{{ url_for('static',filename='base/js/bootstrap.min.js') }}"></script>
  100. <script src="{{ url_for('static',filename='base/js/jquery.singlePageNav.min.js') }}"></script>
  101. <script src="{{ url_for('static',filename='base/js/wow.min.js') }}"></script>
  102. <script src="{{ url_for('static',filename='lazyload/jquery.lazyload.min.js') }}"></script>
  103. <script src="//cdn.bootcss.com/holder/2.9.4/holder.min.js"></script>
  104. <script>
  105. $(function () {
  106. new WOW().init();
  107. })
  108. </script>
  109. <script>
  110. $(document).ready(function () {
  111. $("img.lazy").lazyload({
  112. effect: "fadeIn"
  113. });
  114. $("#do_search").click(function () {
  115. var key = $("#key_movie").val();
  116. location.href = "{{ url_for('home.search',page=1) }}?key=" + key;
  117. });
  118. });
  119. </script>
  120. {% block js %}
  121. {% endblock %}
  122. </body>
  123. </html>

2. 完成登录页面

2.1 定义登录视图函数login

在home目录下创建forms.py文件,用来定义登录的表单LoginForm

可以通过调用LoginForm表单类直接在前端页面上渲染生成登录需要的字段标签

  1. from flask_wtf import FlaskForm
  2. from wtforms.fields import StringField, PasswordField, SubmitField, FileField, TextAreaField
  3. from wtforms.validators import DataRequired, EqualTo, Email, Regexp, ValidationError
  4. from app.models import User
  5. class LoginForm(FlaskForm):
  6. name = StringField(
  7. label="账号",
  8. validators=[
  9. DataRequired("请输入帐号!")
  10. ],
  11. description="账号",
  12. render_kw={
  13. "class": "form-control input-lg",
  14. "placeholder": "请输入帐号!"
  15. }
  16. )
  17. pwd = PasswordField(
  18. label="密码",
  19. validators=[
  20. DataRequired("请输入密码!")
  21. ],
  22. description="密码",
  23. render_kw={
  24. "class": "form-control input-lg",
  25. "placeholder": "请输入密码!",
  26. }
  27. )
  28. submit = SubmitField(
  29. "登录",
  30. render_kw={
  31. "class": "btn btn-lg btn-primary btn-block"
  32. }
  33. )
  34. def validate_name(self, field):
  35. name = field.data
  36. user = User.query.filter_by(name=name).count()
  37. if user == 0:
  38. raise ValidationError("会员账号不存在!")
  39. def validata_pwd(self, field):
  40. from app.models import User
  41. pwd = field.data
  42. name = self.name.data
  43. user = User.query.filter_by(name=name).count()
  44. if not user.check_pwd(pwd):
  45. raise ValidationError("密码错误!")

2.2 定义登录视图函数login

  1. @home.route("/login/", methods=['GET', 'POST'])
  2. def login():
  3. form = LoginForm()
  4. if form.validate_on_submit(): # 如果用户输入的用户名和密码符合验证条件
  5. data = form.data # 获取用户输入的表单数据
  6. user = User.query.filter_by(name=data.get("name")).first() # 根据用户名查询数据库,返回第一个查询结果
  7. if user == None: # 如果从数据库中查不到用户名
  8. flash("会员账号不存在,请重新输入!", "err")
  9. return redirect(url_for("home.login"))
  10. elif not user.check_pwd(data.get("pwd")): # 如果从数据库查询到用户名但密码不匹配
  11. flash("用户名或密码错误!", "err")
  12. return redirect(url_for("home.login"))
  13. session['user'] = user.name # 定义session信息
  14. session['user_id'] = user.id
  15. userlog = Userlog( # 定义用户登录日志
  16. user_id=user.id,
  17. ip=request.remote_addr
  18. )
  19. db.session.add(userlog) # 添加用户登录日志
  20. db.session.commit()
  21. return redirect(url_for("home.user"))
  22. return render_template("home/login.html", form=form)

2.3 在home目录下创建登录前端页面login.html,继承home.html页面

  1. {% extends "home/home.html" %}
  2. {% block content %}
  3. <div class="row">
  4. <div class="col-md-4 col-md-offset-4">
  5. <div class="panel panel-primary">
  6. <div class="panel-heading">
  7. <h3 class="panel-title"><span class="glyphicon glyphicon-log-in"></span>&nbsp;会员登录</h3>
  8. </div>
  9. <div class="panel-body">
  10. <!--消息闪现-->
  11. {% for msg in get_flashed_messages(category_filter=["err"]) %}
  12. <p style="color:red">{{ msg }}</p>
  13. {% endfor %}
  14. {% for msg in get_flashed_messages(category_filter=["ok"]) %}
  15. <p style="color:green">{{ msg }}</p>
  16. {% endfor %}
  17. <form role="form" method="post">
  18. <fieldset>
  19. <div class="form-group">
  20. <label for="input_contact"><span
  21. class="glyphicon glyphicon-user"></span>&nbsp;{{ form.name.label }}</label>
  22. {{ form.name }}
  23. </div>
  24. <!--错误提示-->
  25. {% for err in form.name.errors %}
  26. <div class="col-md-12">
  27. <font style="color:red">{{ err }}</font>
  28. </div>
  29. {% endfor %}
  30. <div class="form-group">
  31. <label for="input_password"><span
  32. class="glyphicon glyphicon-lock"></span>&nbsp;{{ form.pwd.label }}</label>
  33. {{ form.pwd }}
  34. </div>
  35. <!--错误提示-->
  36. {% for err in form.pwd.errors %}
  37. <div class="col-md-12">
  38. <font style="color:red">{{ err }}</font>
  39. </div>
  40. {% endfor %}
  41. {{ form.csrf_token }}
  42. {{ form.submit }}
  43. </fieldset>
  44. </form>
  45. </div>
  46. </div>
  47. </div>
  48. </div>
  49. {% endblock %}

3. 完成退出页面

3.1 定义退出视图函数logout

  1. @home.route("/logout/")
  2. def logout():
  3. session.pop("user", None) # 从session中删除用户名
  4. session.pop("user_id", None) # 从session中删除用户id
  5. return redirect(url_for("home.login"))

3.2 在home目录下创建登录前端页面logout.html,继承home.html页面

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="renderer" content="webkit">
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  8. <meta name="viewport" content="width=device-width, initial-scale=1 , user-scalable=no">
  9. <title>微电影</title>
  10. <link rel="shortcut icon" href="{{ url_for('static',filename='base/images/logo.png') }}">
  11. <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap.min.css') }}">
  12. <link rel="stylesheet" href="{{ url_for('static',filename='base/css/bootstrap-movie.css') }}">
  13. <link rel="stylesheet" href="{{ url_for('static',filename='base/css/animate.css') }}">
  14. <style>
  15. .navbar-brand > img {
  16. display: inline;
  17. }
  18. .media {
  19. padding: 3px;
  20. border: 1px solid #ccc
  21. }
  22. </style>
  23. {% block css %}{% endblock %}
  24. </head>
  25. <body>
  26. <!--导航-->
  27. <nav class="navbar navbar-default navbar-fixed-top">
  28. <div class="container">
  29. <!--小屏幕导航按钮和logo-->
  30. <div class="navbar-header">
  31. <button class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
  32. <span class="icon-bar"></span>
  33. <span class="icon-bar"></span>
  34. <span class="icon-bar"></span>
  35. </button>
  36. <a href="{{ url_for('home.index',page=1) }}" class="navbar-brand" style="width:250px;">
  37. <img src="{{ url_for('static',filename='base/images/logo.png') }}" style="height:30px;">&nbsp;微电影
  38. </a>
  39. </div>
  40. <!--小屏幕导航按钮和logo-->
  41. <!--导航-->
  42. <div class="navbar-collapse collapse">
  43. <form class="navbar-form navbar-left" role="search" style="margin-top:18px;">
  44. <div class="form-group input-group">
  45. <input type="text" class="form-control" placeholder="请输入电影名!" id="key_movie">
  46. <span class="input-group-btn">
  47. <a class="btn btn-default" id="do_search"><span class="glyphicon glyphicon-search"></span>&nbsp;搜索</a>
  48. </span>
  49. </div>
  50. </form>
  51. <ul class="nav navbar-nav navbar-right">
  52. <li>
  53. <a class="curlink" href="{{ url_for('home.index',page=1) }}"><span
  54. class="glyphicon glyphicon-film"></span>&nbsp;电影</a>
  55. </li>
  56. <li>
  57. <a class="curlink" href="{{ url_for('home.login') }}"><span
  58. class="glyphicon glyphicon-log-in"></span>&nbsp;登录</a>
  59. </li>
  60. <li>
  61. <a class="curlink" href="{{ url_for('home.regist') }}"><span
  62. class="glyphicon glyphicon-plus"></span>&nbsp;注册</a>
  63. </li>
  64. <li>
  65. <a class="curlink" href="{{ url_for('home.logout') }}"><span
  66. class="glyphicon glyphicon-log-out"></span>&nbsp;退出</a>
  67. </li>
  68. <li>
  69. <a class="curlink" href="{{ url_for('home.user') }}"><span class="glyphicon glyphicon-user"></span>&nbsp;会员</a>
  70. </li>
  71. </ul>
  72. </div>
  73. <!--导航-->
  74. </div>
  75. </nav>
  76. <!--导航-->
  77. <!--内容-->
  78. {% block content %}
  79. {% endblock %}
  80. <!--内容-->
  81. <!--底部-->
  82. <footer>
  83. <div class="container">
  84. <div class="row">
  85. <div class="col-md-12">
  86. <p>
  87. ©&nbsp;2017&nbsp;flaskmovie.com&nbsp;京ICP备 123456789号
  88. </p>
  89. </div>
  90. </div>
  91. </div>
  92. </footer>
  93. <!--底部-->
  94. <script src="{{ url_for('static',filename='base/js/jquery.min.js') }}"></script>
  95. <script src="{{ url_for('static',filename='base/js/bootstrap.min.js') }}"></script>
  96. <script src="{{ url_for('static',filename='base/js/jquery.singlePageNav.min.js') }}"></script>
  97. <script src="{{ url_for('static',filename='base/js/wow.min.js') }}"></script>
  98. <script src="{{ url_for('static',filename='lazyload/jquery.lazyload.min.js') }}"></script>
  99. <script src="//cdn.bootcss.com/holder/2.9.4/holder.min.js"></script>
  100. <script>
  101. $(function () {
  102. new WOW().init();
  103. })
  104. </script>
  105. <script>
  106. $(document).ready(function () {
  107. $("img.lazy").lazyload({
  108. effect: "fadeIn"
  109. });
  110. $("#do_search").click(function () {
  111. var key = $("#key_movie").val();
  112. location.href = "{{ url_for('home.search',page=1) }}?key=" + key;
  113. });
  114. });
  115. </script>
  116. {% block js %}{% endblock %}
  117. </body>
  118. </html>

4. 完成注册页面

4.1 在home目录下的forms.py文件中,定义注册用的表单类RegistForm

可以通过调用RegistForm类直接在前端页面渲染生成注册使用的字段标签

  1. from flask_wtf import FlaskForm
  2. from wtforms.fields import StringField, PasswordField, SubmitField, FileField, TextAreaField
  3. from wtforms.validators import DataRequired, EqualTo, Email, Regexp, ValidationError
  4. from app.models import User
  5. class RegistForm(FlaskForm):
  6. name = StringField(
  7. label="呢称",
  8. validators=[
  9. DataRequired("请输入呢称!")
  10. ],
  11. description="呢称",
  12. render_kw={
  13. "class": "form-control input-lg",
  14. "placeholder": "请输入呢称!",
  15. }
  16. )
  17. email = StringField(
  18. label="邮箱",
  19. validators=[
  20. DataRequired("请输入邮箱!"),
  21. Email("邮箱格式不正确!"),
  22. ],
  23. description="邮箱",
  24. render_kw={
  25. "class": "form-control input-lg",
  26. "placeholder": "请输入邮箱!"
  27. }
  28. )
  29. phone = StringField(
  30. label="手机号",
  31. validators=[
  32. DataRequired("请输入手机号!"),
  33. Regexp("1[34578]\\d{9}", message="输入的手机号格式不正确!"),
  34. ],
  35. description="手机号",
  36. render_kw={
  37. "class": "form-control input-lg",
  38. "placeholder": "请输入手机号!"
  39. }
  40. )
  41. pwd = PasswordField(
  42. label="密码",
  43. validators=[
  44. DataRequired("请输入密码!")
  45. ],
  46. description="密码",
  47. render_kw={
  48. "class": "form-control input-lg",
  49. "placeholder": "请输入密码!"
  50. }
  51. )
  52. repwd = PasswordField(
  53. label="确认密码",
  54. validators=[
  55. DataRequired("请输入确认密码!"),
  56. EqualTo("pwd", message="两次密码不一致!")
  57. ],
  58. description="确认密码",
  59. render_kw={
  60. "class": "form-control input-lg",
  61. "placeholder": "请输入确认密码!"
  62. }
  63. )
  64. submit = SubmitField(
  65. "注册",
  66. render_kw={
  67. "class": "btn btn-lg btn-success btn-block"
  68. }
  69. )
  70. def validate_name(self, field):
  71. name = field.data
  72. user = User.query.filter_by(name=name).count()
  73. if user == 1:
  74. raise ValidationError("呢称已经存在,请重新输入!")
  75. def validate_email(self, field):
  76. email = field.data
  77. user = User.query.filter_by(email=email).count()
  78. if user == 1:
  79. raise ValidationError("邮箱已经存在,请重新输入!")
  80. def validate_phone(self, field):
  81. phone = field.data
  82. user = User.query.filter_by(phone=phone).count()
  83. if user == 1:
  84. raise ValidationError("手机号已经存在,请重新输入!")

4.2 定义注册视图函数register

  1. @home.route("/register/", methods=["GET", "POST"])
  2. def register():
  3. form = RegistForm() # 获取用户输入的注册信息数据
  4. if form.validate_on_submit(): # 如果用户输入的注册数据通过form基础验证
  5. data = form.data # 获取用户输入的表单数据
  6. user = User(
  7. name=data.get("name"), # 从表单中获取用户输入的用户名
  8. email=data.get("email"), # 从表单中获取用户输入的邮箱地址
  9. phone=data.get("phone"), # 从表单中获取用户输入的手机号
  10. pwd=generate_password_hash(data.get("pwd")), # 从表单中获取用户输入的密码并进行加密
  11. uuid=uuid.uuid4().hex # 生成uuid,保证唯一性
  12. )
  13. db.session.add(user) # 添加用户
  14. db.session.commit() # 向数据库提交用户注册信息
  15. flash("注册成功!", "ok")
  16. return redirect(url_for("home.login"))
  17. return render_template("home/register.html", form=form)

4.3 在home目录下创建登录前端页面register.html,继承home.html页面

  1. {% extends 'home/home.html' %}
  2. {% block content %}
  3. <div class="row">
  4. <div class="col-md-4 col-md-offset-4">
  5. <div class="panel panel-success">
  6. <div class="panel-heading">
  7. <h3 class="panel-title"><span class="glyphicon glyphicon-plus"></span>&nbsp;会员注册</h3>
  8. </div>
  9. <div class="panel-body">
  10. <!--消息闪现-->
  11. {% for msg in get_flashed_messages(category_filter=["err"]) %}
  12. <p style="color:red">{{ msg }}</p>
  13. {% endfor %}
  14. {% for msg in get_flashed_messages(category_filter=["ok"]) %}
  15. <p style="color:green">{{ msg }}</p>
  16. {% endfor %}
  17. <form role="form" method="post">
  18. <fieldset>
  19. <div class="form-group">
  20. <label for="input_name"><span
  21. class="glyphicon glyphicon-user"></span>&nbsp;{{ form.name.label }}</label>
  22. {{ form.name }}
  23. </div>
  24. <!--错误提示-->
  25. {% for err in form.name.errors %}
  26. <div class="col-md-12">
  27. <font style="color:red">{{ err }}</font>
  28. </div>
  29. {% endfor %}
  30. <div class="form-group">
  31. <label for="input_email"><span
  32. class="glyphicon glyphicon-envelope"></span>&nbsp;{{ form.email.label }}</label>
  33. {{ form.email }}
  34. </div>
  35. <!--错误提示-->
  36. {% for err in form.email.errors %}
  37. <div class="col-md-12">
  38. <font style="color:red">{{ err }}</font>
  39. </div>
  40. {% endfor %}
  41. <div class="form-group">
  42. <label for="input_phone"><span
  43. class="glyphicon glyphicon-phone"></span>&nbsp;{{ form.phone.label }}</label>
  44. {{ form.phone }}
  45. </div>
  46. <!--错误提示-->
  47. {% for err in form.phone.errors %}
  48. <div class="col-md-12">
  49. <font style="color:red">{{ err }}</font>
  50. </div>
  51. {% endfor %}
  52. <div class="form-group">
  53. <label for="input_password"><span
  54. class="glyphicon glyphicon-lock"></span>&nbsp;{{ form.pwd.label }}</label>
  55. {{ form.pwd }}
  56. </div>
  57. <!--错误提示-->
  58. {% for err in form.pwd.errors %}
  59. <div class="col-md-12">
  60. <font style="color:red">{{ err }}</font>
  61. </div>
  62. {% endfor %}
  63. <div class="form-group">
  64. <label for="input_repassword"><span
  65. class="glyphicon glyphicon-lock"></span>&nbsp;{{ form.repwd.label }}</label>
  66. {{ form.repwd }}
  67. </div>
  68. <!--错误提示-->
  69. {% for err in form.repwd.errors %}
  70. <div class="col-md-12">
  71. <font style="color:red">{{ err }}</font>
  72. </div>
  73. {% endfor %}
  74. {{ form.submit }}
  75. {{ form.csrf_token }}
  76. </fieldset>
  77. </form>
  78. </div>
  79. </div>
  80. </div>
  81. </div>
  82. {% endblock %}

5. 完成index页面

5.1 定义主页视图函数index

  1. @home.route("/<int:page>/", methods=['GET'])
  2. def index(page=None):
  3. tags = Tag.query.all() # 获取数据库中所有的电影标签
  4. page_data = Movie.query # 从数据库中获取所有的电影信息
  5. tid = request.args.get("tid", 0) # 获取用户请求的电影标签id
  6. if int(tid) != 0:
  7. page_data = page_data.filter_by(tag_id=int(tid)) # 根据用户请求的页码进行过滤
  8. star = request.args.get("star", 0) # 获取用户请求的电影星级id
  9. if int(star) != 0:
  10. page_data = page_data.filter(star=int(star)) # 根据用户请求的电影星级id进行过滤
  11. time = request.args.get("time", 0) # 获取用户请求的电影添加时间
  12. if int(time) != 0:
  13. page_data = page_data.order_by(Movie.addtime) # 获取用户请求的电影添加时间进行过滤
  14. pm = request.args.get("pm", 0) # 获取用户请求的电影播放次数
  15. if int(pm) != 0:
  16. page_data = page_data.order_by(Movie.playnum) # 获取用户请求的电影播放次数进行过滤
  17. cm = request.args.get("cm", 0) # 获取用户请求的电影评论次数
  18. if int(cm) != 0:
  19. page_data = page_data.order_by(Movie.commentnum) # 获取用户请求的电影评论次数进行过滤
  20. if page is None: # 获取用户请求的页数
  21. page = 1
  22. page_data = page_data.paginate(page=page, per_page=10) # 进行分页,每页显示10条电影数据
  23. p = dict(
  24. tid=tid,
  25. star=star,
  26. time=time,
  27. pm=pm,
  28. cm=cm
  29. ) # 定义返回给前端页面的字典信息
  30. return render_template("home/index.html", tags=tags, p=p, page_data=page_data)

5.2 在templates目录下创建ui目录,在ui目录下创建home_page.html,定义分页显示组件

  1. {% macro page(data,url) -%}
  2. {% if data %}
  3. <nav aria-label="Page navigation">
  4. <ul class="pagination">
  5. <li><a href="{{ url_for(url,page=1) }}">首页</a></li>
  6. {% if data.has_prev %}
  7. <li><a href="{{ url_for(url,page=data.prev_num) }}">上一页</a></li>
  8. {% else %}
  9. <li class="disabled"><a href="#">上一页</li>
  10. {% endif %}
  11. {% for v in data.iter_pages() %}
  12. {% if v == data.page %}
  13. <li class="active"><a href="#">{{ v }}</a></li>
  14. {% else %}
  15. <li><a href="{{ url_for(url,page=v) }}">{{ v }}</a></li>
  16. {% endif %}
  17. {% endfor %}
  18. {% if data.has_next %}
  19. <li><a href="{{ url_for(url,page=data.next_num) }}">下一页</a></li>
  20. {% else %}
  21. <li class="disabled"><a href="#">下一页</a></li>
  22. {% endif %}
  23. <li><a href="{{ url_for(url,page=data.pages) }}">尾页</a></li>
  24. </ul>
  25. </nav>
  26. {% endif %}
  27. {%- endmacro %}

5.3 在home目录下创建登录前端页面index.html,继承home.html页面

  1. {% extends "home/layout.html" %}
  2. {% import "ui/home_page.html" as pg %}
  3. {% block content %}
  4. <!--热门电影-->
  5. <section id="hotmovie" style="margin-top:76px">
  6. <div class="container">
  7. <div class="row wow fadeInRight" data-wow-delay="0.6s">
  8. <div class="row">
  9. <iframe class="wow fadeIn" width="100%" height="375px" frameborder=0 scrolling=no
  10. src="{{ url_for('home.animation') }}"></iframe>
  11. </div>
  12. </div>
  13. </div>
  14. </section>
  15. <!--热门电影-->
  16. <!--电影列表-->
  17. <section id="movielist">
  18. <div class="container">
  19. <div class="row wow fadeIn" data-wow-delay="0.6s">
  20. <div class="col-md-12 table-responsive">
  21. <table class="table text-left table-bordered" id="movietags">
  22. <tr>
  23. <td style="width:10%;">电影标签</td>
  24. <td style="width:90%;">
  25. {% for v in tags %}
  26. <a href="{{ url_for('home.index',page=1) }}?tid={{ v.id }}&star={{ p['star'] }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm={{ p['cm'] }}"
  27. class="label label-info"><span
  28. class="glyphicon glyphicon-tag"></span>&nbsp;{{ v.name }}</a>
  29. {% endfor %}
  30. </tr>
  31. <tr>
  32. <td>电影星级</td>
  33. <td>
  34. {% for v in range(1,6) %}
  35. <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ v }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm={{ p['cm'] }}"
  36. class="label label-warning"><span
  37. class="glyphicon glyphicon-star"></span>&nbsp;{{ v }}星</a>
  38. {% endfor %}
  39. </td>
  40. </tr>
  41. <tr>
  42. <td>上映时间</td>
  43. <td>
  44. <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time=1&pm={{ p['pm'] }}&cm={{ p['cm'] }}"
  45. class="label label-default"><span
  46. class="glyphicon glyphicon-time"></span>&nbsp;最近</span></a>
  47. &nbsp;&nbsp;
  48. <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time=2&pm={{ p['pm'] }}&cm={{ p['cm'] }}"
  49. class="label label-default"><span
  50. class="glyphicon glyphicon-time"></span>&nbsp;更早</span></a>
  51. </td>
  52. </tr>
  53. <tr>
  54. <td>播放数量</td>
  55. <td>
  56. <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm=1&cm={{ p['cm'] }}"
  57. class="label label-success"><span class="glyphicon glyphicon-arrow-down"></span>&nbsp;从高到底</span>
  58. </a>
  59. &nbsp;
  60. <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm=2&cm={{ p['cm'] }}"
  61. class="label label-danger"><span class="glyphicon glyphicon-arrow-up"></span>&nbsp;从低到高</span>
  62. </a>
  63. </td>
  64. </tr>
  65. <tr>
  66. <td>评论数量</td>
  67. <td>
  68. <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm=1"
  69. class="label label-success"><span class="glyphicon glyphicon-arrow-down"></span>&nbsp;从高到底</span>
  70. </a>
  71. &nbsp;
  72. <a href="{{ url_for('home.index',page=1) }}?tid={{ p['tid'] }}&star={{ p['star'] }}&time={{ p['time'] }}&pm={{ p['pm'] }}&cm=2"
  73. class="label label-danger"><span class="glyphicon glyphicon-arrow-up"></span>&nbsp;从低到高</span>
  74. </a>
  75. </td>
  76. </tr>
  77. </table>
  78. </div>
  79. {% for v in page_data.items %}
  80. <div class="col-md-3">
  81. <div class="movielist text-center">
  82. <img src="{{ url_for('static',filename='uploads/'+v.logo) }}"
  83. class="img-responsive center-block" alt="">
  84. <div class="text-left" style="margin-left:auto;margin-right:auto;width:210px;">
  85. <span style="color:#999;font-style: italic;">{{ v.title }}</span><br>
  86. <div>
  87. {% for val in range(1,v.star+1) %}
  88. <span class="glyphicon glyphicon-star" style="color:#FFD119"></span>
  89. {% endfor %}
  90. {% for val in range(1,6-v.star) %}
  91. <span class="glyphicon glyphicon-star-empty" style="color:#FFD119"></span>
  92. {% endfor %}
  93. </div>
  94. </div>
  95. <a href="{{ url_for('home.play',id=v.id,page=1) }}" class="btn btn-primary" target="_blank"
  96. role="button"><span
  97. class="glyphicon glyphicon-play"></span>&nbsp;播放</a>
  98. </div>
  99. </div>
  100. {% endfor %}
  101. <div class="col-md-12">
  102. {{ pg.page(page_data,'home.index') }}
  103. </div>
  104. </div>
  105. </div>
  106. </section>
  107. <!--电影列表-->
  108. {% endblock %}

至此,电影网站的首页面开发完成了

Flask开发微电影网站(三)的更多相关文章

  1. Flask开发微电影网站(一)

    1.用到的Flask知识 1.使用整形,浮点型,路径型,字符串型下正则表达式路由转化器 2.使用GET与POST请求,上传文件,cookie获取与响应,404处理 3.使用模板自动转义,定义过滤器,定 ...

  2. Flask开发微电影网站(五)

    后台管理页面是系统管理员登录后对网站进行管理的前端页面 后台登录页面,如下图所示 管理员登录后的页面,如下图所示 管理员登录后,在右上角显示的管理员信息,如下图所示 管理员登录后,在页面中间部分的左侧 ...

  3. Flask开发微电影网站(七)

    1.后台管理之电影管理 1.1 定义电影表单 在app的admin目录的forms.py文件中,定义电影表单 # 电影表单 class MovieForm(FlaskForm): title = St ...

  4. Flask开发微电影网站(六)

    1. 后台管理登录功能实现 1.1 后台管理页面登录表单LoginForm 在app的admin目录下创建forms.py文件,用来保存admin蓝图中需要使用到的表单 from flask_wtf ...

  5. Flask开发微电影网站(二)

    1.安装数据库连接依赖包 pip install flask-sqlalchemy 2.创建movie数据库 在CentOS虚拟机,进入MaridDB数据库提示符,创建movie数据库 create ...

  6. Flask开发微电影网站(十)

    1.后台管理之角色管理 1.1 角色管理之定义角色表单 在app的admin目录的forms.py文件中,定义角色表单 # 角色表单 class RoleForm(FlaskForm): name = ...

  7. Flask开发微电影网站(九)

    1.后台管理之电影管理 1.1 电影管理之所有电影收藏列表 1.1.1 电影管理之电影收藏列表视图函数 在admin目录下的views.py文件中定义电影收藏列表视图函数 电影收藏列表视图函数需要被登 ...

  8. Flask开发微电影网站(八)

    1.后台管理之电影预告管理 1.1 定义电影预告表单 在app的admin目录的forms.py文件中,定义电影预告表单 # 预告表单 class PreviewForm(FlaskForm): ti ...

  9. Flask开发微电影网站(四)

    会员中心页面,如下图所示 用户登录后,修改密码页面,如下图所示 用户查看自己的评论页面,如下图所示 用户查看自己的登录日志页面,如下图所示 用户查看自己收藏的电影的页面,如下图所示 1. 定义用户主页 ...

随机推荐

  1. Mac OS X下各种文件编码的转换方法

    何曾几时本猫还在windows下编码的时候,那时ruby的源代码的编码格式都是gbk啊!导致N多中文显示为乱码.后来无奈写了个转换代码从gbk编码转为utf-8格式的小工具: #!/usr/bin/r ...

  2. WebDriver元素等待机制

    能否构建健壮和可靠的测试是UI自动化测试能否成功的关键因素之一.但实际情况是当一个测试接着一个测试执行的时候,常会遇到各种不同的状况.比如脚本去定位元素或去验证程序的运行状态时,有时会发现找不到元素, ...

  3. vue2.0-基于elementui换肤[自定义主题]

    0. 直接上 预览链接 vue2.0-基于elementui换肤[自定义主题] 1. 项目增加主题组件 在项目的src/components下添加skin文件夹 skin文件获取地址 2. 项目增加自 ...

  4. WebStorm常用快捷键总结

    在使用WebStorm的过程中,常用快捷键整理: 1.  必备快捷键 Ctrl+/:注释当前行 Ctrl+Shift+/:当前位置插入注释 Ctrl+Alt+/:块注释,并Focus到首行,写注释说明 ...

  5. Tihinkphp3.2整合最新版阿里大鱼进行短信验证码发送

    阿里大鱼最新下载地址:阿里大鱼SDK下载 或者从官网进行下载:阿里大鱼SDK官网下载 下载完成后,将压缩包内的api_sdk文件夹放到ThinkPHP\Library\Vendor目录下,修改文件名为 ...

  6. OOP的基本原则

    OOP的基本原则 点击打开链接

  7. java并发容器(Map、List、BlockingQueue)

    转发: 大海巨浪 Java库本身就有多种线程安全的容器和同步工具,其中同步容器包括两部分:一个是Vector和Hashtable.另外还有JDK1.2中加入的同步包装类,这些类都是由Collectio ...

  8. OAuth 2.0中文译本

    (一)背景知识 OAuth 2.0很可能是下一代的“用户验证和授权”标准,目前在国内还没有很靠谱的技术资料.为了弘扬“开放精神”,让业内的人更容易理解“开放平台”相关技术,进而长远地促进国内开放平台领 ...

  9. Mina框架(实战详解)

    Apache Mina Server 是一个网络通信应用框架,为开发高性能和高可用性的网络应用程序提供了非常便利的框架. 特点:异步的NIO框架,将UDP当成"面向连接"的协议 一 ...

  10. java运行机制、Jdk版本及Java环境变量

    一.语言特性 计算机高级语言按程序的执行方式可分为:编译型和解释型两种.编译型的语言是指使用专门的编译器,针对特定的平台(操作系统)一次性翻译成被该平台硬件执行的机器码,并包装成该平台可执行性程序文件 ...