今天給你們帶來的是模板項目實戰,先給你們看一下效果圖javascript
說明:css
點擊圖片後會跳轉到對應的詳情頁面html
數據:前端
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'托馬斯·哈登·丘奇 / 泰倫斯·霍華德 / 波伊德·霍布魯克 / 瑞斯·維克菲爾德 / 馬爾洛·托馬斯 /' } ]
頁面只顯示三個java
下面淺藍色爲背景色。python
咱們先來完成首頁的功能web
你們能夠先本身試着作一下,而後再看船長的代碼:面試
先新建一個項目microPro
:flask
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>
上面咱們利用宏
將首頁代碼進行了第一次優化。若是咱們如今還有其餘頁面,試想一下,首頁上面的搜索框
以及頁面背景
是否能夠提取爲公用的,其餘頁面在應用到的時候經過繼承來實現呢?答案是確定的。
因此咱們如今新建base.html
文件,而且將頁面佈局代碼,提出,再想一下,既然名爲公用也就意味着其餘代碼也能夠繼承這個base.html
,那麼頁面內容:
這部分代碼是否是就不能夠再在base.html
裏了【答:是】,可是咱們又要往base.html
這裏面插入上圖部分代碼,那要用什麼呀?block
對吧。此外,按照習慣,咱們一樣將樣式style
以文件的形式提取出來,此時頭部搜索樣式與內容部分樣式確定是不能提取在一個文件裏的,由於在一個文件裏每次都會加載全部的代碼,這樣在head
中就不必加載內容的樣式,因此咱們把樣式分別提取成css
文件,一個是搜索欄和頁面背景,命名爲base.css
:
*{ 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;}
另外一個是頁面樣式,命名爲index_page.css
:
.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;}
在static
文件夾下新建css
文件夾,而後分別新建以上兩個文件:
綜上,咱們最後base.html
文件代碼應該以下:
base.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首頁</title> <link rel="stylesheet" href="{{ url_for('static', filename='css/base.css') }}"> {% block head %}{% endblock %} </head> <body> <div class="page"> {# 搜索框 #} <div class="searich-group"> <input class="search-input" type="text" placeholder="請輸入查詢條件"> </div> {% block content %}{% endblock %} </div> </body> </html>
其中block head
填充的是內容部分的樣式代碼。
如今公用部分已經提取好,回到index.html
,咱們發現要作的工做只須要
1.繼承`base.html` 2\. 填充`block`
便可。
index.html
{% extends 'base.html' %} {% block head %} <link rel="stylesheet" href="{{ url_for('static', filename='css/index_page.css') }}"> {% endblock %} {% block content %} {% 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 %} {# 電影 #} {{ listGroup('電影', movies) }} {# 電視劇 #} {{ listGroup('電視劇', tvs) }} {% endblock %}
執行文件,頁面顯示不變。
接着咱們來完成更多
的模塊,點擊更多
後頁面顯示效果如上圖。
咱們先來分析上面這個頁面,咱們發現除了搜索欄下面的圖片區域有些變化之外,其他都是base.html
的佈局,因此咱們首先想到能夠繼承base.html
,而圖片顯示規則則和咱們前面定義過的宏
徹底一致,咱們就能夠導入寫好的宏
。
因此咱們先在templates
文件夾下新建moreList.html
文件:
咱們已經在base.html
中保留了block
,因此頁面新的佈局只須要經過block
進行插入便可:
moreList.html
{% extends 'base.html' %}
{% from 'macros/macros.html' import itemGroup %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/item.css') }}"> <style> .content{ padding: 25px 10px; } </style> {% endblock %} {% block content %} <div class="content"> {% for item in items %} {{ itemGroup(item) }} {% endfor %} </div> {% endblock %}
若是對軟件測試、接口測試、自動化測試、面試經驗交流。感興趣能夠加軟件測試交流:1085991341,還會有同行一塊兒技術交流。
固然,咱們還要將更多
加上連接,咱們先定義函數:
@app.route('/list/<int:category>/')def itemList(category): # 若是category等於1:返回電影 # 若是category等於2:返回電視劇 # 不然返回空數組 items = [] if category == 1: items = movies elif category == 2: items = tvs else: items = [] return flask.render_template('moreList.html', items=items)
這裏咱們新加了一個整型的category
參數,方便咱們對進入的頁面究竟是電影仍是電視劇進行分辨,在macros.html
文件中須要加上更多的連接:
<a href="{{ url_for('itemList', category=category) }}" class="more-btn">更多</a>
這樣就會完成點擊更多
後的頁面跳轉和跳轉後的頁面佈局了。以上就是一個完整的一個項目實戰實操,以上內容但願對你有幫助,有被幫助到的朋友歡迎點贊,評論。