专栏首页自动化测试实战flask第35篇——模板项目实战(一)

flask第35篇——模板项目实战(一)

先给大家看一下效果图

说明:

  • 点击图片后会跳转到对应的详情页面
  • 数据:
movies = [
    {
        'id': '34532',
        'title': u'胖子行动队',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2526215398.webp',
        'rating': u'7.6',
        'comment_count': 39450,
        'authors': u'宝贝儿 / 李成敏 Clara Lee / 文章 Zhang Wen'
    },
    {
        'id': '394558',
        'title': u'李茶的姑妈',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2533384240.webp',
        'rating': u'6.3',
        'comment_count': 38409,
        'authors': u'钱晨光 / 吴瑾蓉 / 黄才伦'
    },
    {
        'id': '26921827',
        'title': u'找到你',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2534471408.webp',
        'rating': u'4.3',
        'comment_count': 682,
        'authors': u'姚晨 / 马伊琍 / 袁文康'
    },
    {
        'id': '26287884',
        'title': u'悲伤逆流成河',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2529701498.webp',
        'rating': u'7.5',
        'comment_count': 33060,
        'authors': u'赵英博 / 任敏 / 辛云来'
    },
    {
        'id': '26287884',
        'title': u'嗝嗝老师',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2535365481.webp',
        'rating': u'7.5',
        'comment_count': 33060,
        'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
    }
]

# 电视剧
tvs = [
    {
        'id': '235434',
        'title': u'如懿传',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2460165077.jpg',
        'rating': u'7.4',
        'comment_count': 49328,
        'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
    },
    {
        'id': '48373095',
        'title': u'奇葩说第五季',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2534020405.jpg',
        'rating': u'8.4',
        'comment_count': 2483,
        'authors': u'伊藤沙莉 / 中川大志 / 上原实矩 / 森绘梨佳 / 樱田通 /'
    },

    {
        'id': '27005982',
        'title': u'最亲爱的你',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2508399162.jpg',
        'rating': u'7.6',
        'comment_count': 25532,
        'authors': u'杰西·普莱蒙 / 莫莉·香侬 / 布莱德利·惠特福德 / Maude Apatow / 麦迪逊·贝蒂 /'
    },
    {
        'id': '30290917',
        'title': u'我们无法成为野兽',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2537556934.jpg',
        'rating': u'3.7',
        'comment_count': 8493,
        'authors': u'钟汉良 / 杨颖 / 甘婷婷 / 孙艺洲 / 亓航 /'
    },
    {
        'id': '292843',
        'title': u'奇遇人生',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2533929218.jpg',
        'rating': u'8.2',
        'comment_count': 23456,
        'authors': u'托马斯·哈登·丘奇 / 泰伦斯·霍华德 / 波伊德·霍布鲁克 / 瑞斯·维克菲尔德 / 马尔洛·托马斯 /'
    }
]
  • 说明
  1. 页面只显示三个
  2. 下面浅蓝色为背景色。

我们先来完成首页的功能

大家可以先自己试着做一下,然后再看船长的代码:

先新建一个项目microPro

app.py

# coding: utf-8

from flask import Flask
import flask

app = Flask(__name__)  # type: Flask
app.debug = True

# 电影
movies = [
    {
        'id': '34532',
        'title': u'胖子行动队',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2526215398.webp',
        'rating': u'7.6',
        'comment_count': 39450,
        'authors': u'宝贝儿 / 李成敏 Clara Lee / 文章 Zhang Wen'
    },
    {
        'id': '394558',
        'title': u'李茶的姑妈',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2533384240.webp',
        'rating': u'6.3',
        'comment_count': 38409,
        'authors': u'钱晨光 / 吴瑾蓉 / 黄才伦'
    },
    {
        'id': '26921827',
        'title': u'找到你',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2534471408.webp',
        'rating': u'4.3',
        'comment_count': 682,
        'authors': u'姚晨 / 马伊琍 / 袁文康'
    },
    {
        'id': '26287884',
        'title': u'悲伤逆流成河',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2529701498.webp',
        'rating': u'7.5',
        'comment_count': 33060,
        'authors': u'赵英博 / 任敏 / 辛云来'
    },
    {
        'id': '26287884',
        'title': u'嗝嗝老师',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2535365481.webp',
        'rating': u'7.5',
        'comment_count': 33060,
        'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
    }
]

# 电视剧
tvs = [
    {
        'id': '235434',
        'title': u'如懿传',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2460165077.jpg',
        'rating': u'7.4',
        'comment_count': 49328,
        'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
    },
    {
        'id': '48373095',
        'title': u'奇葩说第五季',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2534020405.jpg',
        'rating': u'8.4',
        'comment_count': 2483,
        'authors': u'伊藤沙莉 / 中川大志 / 上原实矩 / 森绘梨佳 / 樱田通 /'
    },

    {
        'id': '27005982',
        'title': u'最亲爱的你',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2508399162.jpg',
        'rating': u'7.6',
        'comment_count': 25532,
        'authors': u'杰西·普莱蒙 / 莫莉·香侬 / 布莱德利·惠特福德 / Maude Apatow / 麦迪逊·贝蒂 /'
    },
    {
        'id': '30290917',
        'title': u'我们无法成为野兽',
        'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2537556934.jpg',
        'rating': u'3.7',
        'comment_count': 8493,
        'authors': u'钟汉良 / 杨颖 / 甘婷婷 / 孙艺洲 / 亓航 /'
    },
    {
        'id': '292843',
        'title': u'奇遇人生',
        'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2533929218.jpg',
        'rating': u'8.2',
        'comment_count': 23456,
        'authors': u'托马斯·哈登·丘奇 / 泰伦斯·霍华德 / 波伊德·霍布鲁克 / 瑞斯·维克菲尔德 / 马尔洛·托马斯 /'
    }
]

@app.route('/')
def hello_world():
    context = {
        "movies": movies,
        "tvs": tvs
    }
    return flask.render_template('index.html', **context)

if __name__ == '__main__':
    app.run()

这里只需要渲染数据即可,即将**context传给模板。

index.html

<!DOCTYPE html>
 <html lang="en">
 <head>
      <meta charset="UTF-8">
      <title>首页</title>
      <style>
         *{
             padding: 0;             
             margin: 0;
             list-style: none;             
             text-decoration: none;
             font-family: "Microsoft Ya Hei";
          }

         .page{
             width: 375px;
             height: 667px;             
             background: #d1fcff;
          }

         .page .searich-group{
             padding: 14px 8px;
             background: #41b357;
          }

         .page .searich-group .search-input{
             {# 块级元素 #}
             display: block;
             height: 30px;             
             width: 100%;             
             background: #fff;
             {# 与盒子整体匹配 #}             
             box-sizing: border-box;
             {# 搜索框不显示 #}
             border: none;
             {# 鼠标点击搜索框后不显示边框 #}
             outline: none;
             {# 边框圆角 #}
             border-radius: 5px;
          }
          
          .list-group{
             background: #fff;
             padding: 17px 18px;
          }
          
          .list-group .group-top{
             font-size: 18px;
             {# 获取浮动元素 #}
             overflow: hidden;
          }
          
          .group-top .group-title{
             float: left;
             color: #000;
          }
          
          .group-top .more-btn{
             float: right;
          }
          
          .any-group{
             margin-top: 20px;
             overflow: hidden;
          }

          .any-group .item-group{
             width: 100px;
             float: left;
             margin-right: 8px;
          }
          
          .item-group .thumbnail{
             width: 100%;
             height: 140px;
          }
          
          .item-group .item-title{
             text-align: center;
             margin-top: 12px;
          }

          .item-group .item-rating{
             color: #acacac;
             text-align: center;
             font-size: 12px;
          }
          
          .item-rating img{
             width: 10px;
             height: 10px;
          }
      </style>

 </head>
 <body>
      <div class="page">
      {# 搜索框 #}
      <div class="searich-group">
          <input class="search-input" type="text" placeholder="请输入查询条件">
      </div>
      {# 电影 #}
      <div class="list-group">
          <div class="group-top">
              <span class="group-title">电影</span>
              <a href="#" class="more-btn">更多</a>
          </div>
          <div class="any-group">
              {% for movie in movies[0:3] %}
                  <div class="item-group">
                      <img src="{{ movie.thumbnail }}" class="thumbnail" alt="">
                      <p class="item-title">{{ movie.title }}</p>
                      <p class="item-rating">
                      {# 确定整星个数 #}
                      {% set lights = ((movie.rating|int)/2)|int %}
                      {# 确定半个星个数 #}
                      {% set halfs = ((movie.rating|int)%2) %}
                      {# 灰色星星个数 #}
                      {% set grays = 5 - lights - halfs %}
                      {# 渲染高亮星星 #}
                      {% for light in range(0, lights) %}
                          <img src="{{ url_for('static', filename='img/rate_light.png') }}">
                      {% endfor %}
                      {# 渲染半高亮星星 #}
                      {% for light in range(0, halfs) %}
                          <img src="{{ url_for('static', filename='img/rate_half.jpg') }}">
                      {% endfor %}
                      {# 渲染灰色星星 #}
                      {% for light in range(0, grays) %}
                          <img src="{{ url_for('static', filename='img/rate_gray.png') }}">
                      {% endfor %}
                      {{ movie.rating }}
                      </p>
                  </div>
              {% endfor %}
          </div>
      </div>

      {# 电视剧 #}
               <div class="list-group">
                   <div class="group-top">
                       <span class="group-title">电视剧</span> 
                            <a href="#" class="more-btn">更多</a>
                   </div>    
                   <div class="any-group"> 
                       {% for tv in tvs[0:3] %}        
                            <div class="item-group">  
                                <img src="{{ tv.thumbnail }}" class="thumbnail" alt="">
                                <p class="item-title">{{ tv.title }}</p> 
                                <p class="item-rating">
                                    {# 确定整星个数 #}
                                    {% set lights = ((tv.rating|int)/2)|int %} 
                                    {# 确定半个星个数 #}
                                    {% set halfs = ((tv.rating|int)%2) %}
                                    {# 灰色星星个数 #}
                                    {% set grays = 5 - lights - halfs %}
                                    {# 渲染高亮星星 #}
                                    {% for light in range(0, lights) %}
                                        <img src="{{ url_for('static', filename='img/rate_light.png') }}">
                                    {% endfor %}
                                    {# 渲染半高亮星星 #}
                                    {% for light in range(0, halfs) %}
                                        <img src="{{ url_for('static', filename='img/rate_half.jpg') }}">
                                    {% endfor %}
                                    {# 渲染灰色星星 #}
                                    {% for light in range(0, grays) %}
                                        <img src="{{ url_for('static', filename='img/rate_gray.png') }}">
                                    {% endfor %}
                                    {{ tv.rating }}
                                </p>
                            </div>
                     {% endfor %}
                 </div>
             </div>
          </div>
      </body>
 </html>

上面代码综合了之前学过的知识,包括:flask for 循环set模板赋值其余都是前端的内容,这里不做过多的阐述。

  • 分析优化

观察index.html中设置星星显示数量代码,我们发现在电影和电视剧两部分的代码是大体一致的,遇到重复代码就要想到优化,这里就可以用到我们学过的来简化上面的代码:

<div class="list-group">
    <div class="group-top">
    <span class="group-title">电影</span>
    <a href="#" class="more-btn">更多</a>
</div>
<div class="any-group">
    {% for movie in movies[0:3] %}
        <div class="item-group">
            <img src="{{ movie.thumbnail }}" class="thumbnail" alt="">
            <p class="item-title">{{ movie.title }}</p>
            <p class="item-rating">
                {# 确定整星个数 #}
                {% set lights = ((movie.rating|int)/2)|int %}
                {# 确定半个星个数 #}
                {% set halfs = ((movie.rating|int)%2) %}
                {# 灰色星星个数 #}
                {% set grays = 5 - lights - halfs %}
                {# 渲染高亮星星 #}
                {% for light in range(0, lights) %}
                    <img src="{{ url_for('static', filename='img/rate_light.png') }}">
                {% endfor %}
                {# 渲染半高亮星星 #}
                {% for light in range(0, halfs) %}
                    <img src="{{ url_for('static', filename='img/rate_half.jpg') }}">
                {% endfor %}
                {# 渲染灰色星星 #}
                {% for light in range(0, grays) %}
                    <img src="{{ url_for('static', filename='img/rate_gray.png') }}">
                {% endfor %}
                {{ movie.rating }}
            </p>
        </div>
    {% endfor %}
</div>

将以上代码提取出来作为宏,我们发现变化的只有两个——电影/电视剧movies/tvs,其余都一样,所以我们可以将这两个作为变量传入:

  • 第一次优化——宏
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
    <style>
        *{
            padding: 0;
            margin: 0;
            list-style: none;
            text-decoration: none;
            font-family: "Microsoft Ya Hei";

        }
        .page{
            width: 375px;
            height: 667px;
            background: #d1fcff;
        }
        .page .searich-group{
            padding: 14px 8px;
            background: #41b357;
        }
        .page .searich-group .search-input{
        {# 块级元素 #}
            display: block;
            height: 30px;
            width: 100%;
            background: #fff;
        {# 与盒子整体匹配 #}
            box-sizing: border-box;
        {# 搜索框不显示 #}
            border: none;
        {# 鼠标点击搜索框后不显示边框 #}
            outline: none;
        {# 边框圆角 #}
            border-radius: 5px;
        }
        .list-group{
            background: #fff;
            padding: 17px 18px;
        }
        .list-group .group-top{
            font-size: 18px;
        {# 获取浮动元素 #}
            overflow: hidden;
        }
        .group-top .group-title{
            float: left;
            color: #000;
        }
        .group-top .more-btn{
            float: right;
        }
        .any-group{
            margin-top: 20px;
            overflow: hidden;
        }
        .any-group .item-group{
            width: 100px;
            float: left;
            margin-right: 8px;
        }
        .item-group .thumbnail{
            width: 100%;
            height: 140px;
        }
        .item-group .item-title{
            text-align: center;
            margin-top: 12px;
        }
        .item-group .item-rating{
            color: #acacac;
            text-align: center;
            font-size: 12px;
        }
        .item-rating img{
            width: 10px;
            height: 10px;
        }
    </style>
</head>
<body>
    {% macro listGroup(category, items) %}
        <div class="list-group">
            <div class="group-top">
                <span class="group-title">{{ category }}</span>
                <a href="#" class="more-btn">更多</a>
            </div>
            <div class="any-group">
                {% for item in items[0:3] %}
                    <div class="item-group">
                    <img src="{{ item.thumbnail }}" class="thumbnail" alt="">
                    <p class="item-title">{{ item.title }}</p>
                    <p class="item-rating">
                        {# 确定整星个数 #}
                        {% set lights = ((item.rating|int)/2)|int %}
                        {# 确定半个星个数 #}
                        {% set halfs = ((item.rating|int)%2) %}
                        {# 灰色星星个数 #}
                        {% set grays = 5 - lights - halfs %}
                        {# 渲染高亮星星 #}
                        {% for light in range(0, lights) %}
                            <img src="{{ url_for('static', filename='img/rate_light.png') }}">
                        {% endfor %}
                        {# 渲染半高亮星星 #}
                        {% for light in range(0, halfs) %}
                            <img src="{{ url_for('static', filename='img/rate_half.jpg') }}">
                        {% endfor %}
                        {# 渲染灰色星星 #}
                        {% for light in range(0, grays) %}
                            <img src="{{ url_for('static', filename='img/rate_gray.png') }}">
                        {% endfor %}

                        {{ item.rating }}
                    </p>
                </div>
                {% endfor %}
            </div>
        </div>
    {% endmacro %}
    <div class="page">
        {# 搜索框 #}
        <div class="searich-group">
            <input class="search-input" type="text" placeholder="请输入查询条件">
        </div>
        {# 电影 #}
        {{ listGroup('电影', movies) }}
        {# 电视剧 #}
        {{ listGroup('电视剧', tvs) }}
    </div>
</body>
</html>

本文分享自微信公众号 - 自动化测试实战(gh_839e78b6ba28)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-10-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • selenium 上传文件方法补充——SendKeys、win32gui

    用户2149234
  • 在自动化测试中,重要的不是工具

    经常有人在公众号留言或是微信问我,做自动化测试用什么工具好,或是学哪门编程语言好呢?

    用户2149234
  • Appium+python(1)简单的介绍环境搭建

    用户2149234
  • python flask web开发实战 bootstrap

    from flask.ext.bootstrap import Bootstrap

    用户5760343
  • MVC和三层,我的一个不成熟的看法,大家批批

      这里说的MVC指的是设计模式里的MVC不是asp.net mvc。   既然MVC是一种设计模式,那么他就应该在任何地方都可以使用。比如三层。   有人说...

    用户1174620
  • bootstrap3 上中下页面布局

    用户5760343
  • Bootstrap响应式前端框架笔记十四——媒体对象与列表组

        在移动开发中经常会使用到列表,使用媒体对象可以方便的创建列表中每一行元素,常规的媒体对象实例如下:

    珲少
  • 25、商品详情页

    (1)复制一份test.vue文件并重命名为goodsDetail作为我们的商品详情页面

    Ewall
  • KVO实现原理

    概览 本文分为两个大的方面。一、kvo的简单使用场景。二、kvo的来龙去脉,讲讲苹果的实现。 KVO 使用方法,和常用场景。 Key-value obser...

    MelonTeam
  • Django+xadmin打造在线教育平台(七)

    代码 github下载 十、授课教师  10.1.讲师列表页 拷贝teacher-list.html和teacher-detail.html到template...

    zhang_derek

扫码关注云+社区

领取腾讯云代金券