先给大家看一下效果图
说明:
- 点击图片后会跳转到对应的详情页面
- 数据:
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'托马斯·哈登·丘奇 / 泰伦斯·霍华德 / 波伊德·霍布鲁克 / 瑞斯·维克菲尔德 / 马尔洛·托马斯 /'
}
]
- 说明
- 页面只显示三个
- 下面浅蓝色为背景色。
我们先来完成首页的功能
大家可以先自己试着做一下,然后再看船长的代码:
先新建一个项目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>