多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > Flask Web 開發學習稿(一)

Flask Web 開發學習稿(一)

來源:程序員人生   發布時間:2016-06-08 17:38:02 閱讀次數:2982次

好久沒有更新過了,把這些日子弄的東西先放1波出來
這個學習筆記未必會包括全部章節,有時會將兩個章節進行合并

第1章 安裝

1.1 使用虛擬環境

虛擬環境是 Python 解釋器的1個私有副本,可以安裝私有包而不影響全局 Python 解釋器

Python 3.3 通過 venv 模塊原生支持虛擬環境,命令為 pyvenv 。不過在 Python 3.3 中使用 pyvenv 命令創建的虛擬環境不包括 pip ,在 Python 3.4 中改進了這1缺點。

我這邊使用 Python 3.5.0 和 Pycharm 來進行學習,所以暫時不使用這個,Pycharm 可以很好的解決各個項目的版本的虛擬環境問題。

1.2 使用 pip 安裝 Python 包

使用 (venv) $ pip install flask 可以在虛擬環境中安裝 Flask

第2章 程序的基本結構

2.1 初始化

Web 服務器使用1種名為 Web 服務器網關接口的協議,把接收自客戶真個所有要求都轉交給這個對象處理
Flask 類的構造函數只有1個必須指定的參數,即程序主模塊或包的名字。Flask 用這個參數決定程序的根目錄,以便找到相對程序根目錄的資源文件位置。在大多數程序中,Python 的 __name__ 變量就是所需的值。

2.2 路由和視圖函數

程序實例保存了1個 URL 到 Python 函數的映照關系,處理 URL 和函數之間關系的程序成為路由。
Flask 中定義路由最簡單的方式是使用程序提供的 app.route 修飾器,把修飾的函數注冊為路由。

@app.route('/') def index(): return '<h1>Hello World!</h1>'

修飾器是 Python 語言的標準特性,可使用不同的方式修改函數的行動

把 index 函數注冊為程序跟地址的處理程序,不過在 Pthon 代碼中嵌入響應字符串會致使代碼難以保護,以后將會介紹生成響應的正確方法。像 index 這樣的函數稱為視圖函數。
地址中也能夠包括可變部份,可以在路由中定義可變的這部份

@app.route('/user/<name>') def user(name): return '<h1>Hello, %s!</h1>' % name

尖括號中的內容是動態部份,任何能匹配靜態部份的 URL 都會映照到這個路由上。

2.3 - 2.4 啟動服務器

用 run 方法來啟動 Flask 集成的開發 Web 服務器

from flask import Flask app = Flask(__name__) @app.route('/') def index(): return '<h1>Hello World!</h1>' if __name__ == '__main__': app.run(debug=True)

使用__name__ == '__main__'是 Python 的慣用法,確保直接履行此腳本時才啟動服務器,若其他程序調用該腳本可能父級程序會啟動不同的服務器,就不履行 app.run 了
在 Pycharm 中啟動后,可以看到 Flask 為我們啟動了1個調試實例
1.png
通過閱讀器訪問,可以發現已成功的訪問了,而且調試器中也記錄下了這次訪問
這里寫圖片描述
我們可以和前面的動態部份結合起來,變成1個根據不同地址顯示不同頁面的服務,可以看到服務器已記錄下了兩次訪問,其中1次使用路徑進來,響應中也帶有相應信息,表示已成功
這里寫圖片描述
這里寫圖片描述

2.5 要求-響應循環

2.5.1 程序和要求上下文

為了不在需要使用訪問對象時,都將其作為參數傳入。Flask 使用上下文臨時把某些對象變成全局可訪問

from flask import Flask from flask import request app = Flask(__name__) @app.route('/') def index(): user_agent = request.headers.get('User-Agent') return '<p>Your Browser is %s!</p>' % user_agent if __name__ == '__main__': app.run(debug=True)

這里寫圖片描述
在這個視圖函數中,我們把 request 當作全局變量使用,事實上 request 不多是全局變量,而 Flask 使用上下文讓特定的變量在1個線程中全局可訪問,與此同時還不會干擾其他線程。

線程是可單獨管理的最小指令集,多線程 Web 服務器會創建1個線程池
再從線程池當選擇1個線程用于處理接收到的要求

在 Flask 中有兩種上下文:程序上下文和要求上下文,這兩種上下文提供的變量以下:

變量名 上下文 說明
current_app 程序上下文 當前激活程序的程序實例
g 程序上下文 處理要求時用作臨時存儲的對象,每次要求都會重設這個變量
request 要求上下文 要求對象,封裝了客戶端發出的 HTTP 要求中的內容
session 要求上下文 用戶繪畫,用戶存儲要求之間需要“記住”的值的字典

Flask 會在分發要求之前激活程序和要求上下文,要求處理完成后再將其刪除

2.5.2 要求調度

Flask 使用 app.route 修飾器或非修飾器情勢的 app.add_url_rule() 生成映照
想要查看 Flask 程序中的 URL 映照是甚么模樣,我們可以在 Python Shell 中檢查為 hello》py 生成的映照

from hello import app app.url_map

2.5.3 要求鉤子

有時在處理要求之前或以后履行代碼會很有用,Flask 提供了注冊通用函數的功能,注冊的函數可在要求被分發到視圖函數之前或以后調用。要求鉤子使用修飾器實現。Flask 支持以下4種鉤子:

鉤子名 上下文
before_first_request 注冊1個函數,在處理第1個要求之前運行
before_request 注冊1個函數,在每次要求之前運行
after_request 注冊1個函數,如果沒有未處理的異常拋出,在每次要求后運行
teardown_request 注冊1個函數,即便有未處理的異常拋出,也在每次要求后運行

Flask 會在分發要求之前激活程序和要求上下文,要求處理完成后再將其刪除
在要求鉤子函數和視圖函數之間同享數據1般使用上下文全局變量g

2.5.4 響應

Flask 調用視圖函數后,會將其返回值作為響應的內容。如果視圖函數返回的響應需要使用不同的狀態碼,那末可以把數字代碼作為第2個返回值,添加到響應文本以后。

from flask import Flask from flask import request app = Flask(__name__) @app.route('/') def index(): return '<p>Bad Request !</p>', 400 if __name__ == '__main__': app.run(debug=True)

可以看到閱讀器中直接顯示了 HTPP 400 毛病。視圖函數返回的響應還可以接受第3個參數,這是1個由首部組成的字典,可以添加到 HTTP 響應中。
如果不想返回由多個值組成的元組,Flask 視圖函數還可以返回 Response 對象。make_response() 函數可接受1/2/3個參數,并返回1個 Response 對象。

from flask import Flask from flask import make_response from flask import redirect app = Flask(__name__) @app.route('/') def index(): response = make_response('<h1>This document carries a cookie!</h1>') response.set_cookie('answer', '42') return response @app.route('/<name>') def user(name): return redirect('http://www.baidu.com') if __name__ == '__main__': app.run(debug=True)

可以看到,已被設置好了 Cookie
這里寫圖片描述
如果在地址中訪問/txb則會被重定向到百度去
還有1種特殊的響應由 abort 函數生成,用于毛病處理

from flask import Flask from flask import make_response from flask import abort app = Flask(__name__) @app.route('/') def index(): response = make_response('<h1>This document carries a cookie!</h1>') response.set_cookie('answer', '42') return response @app.route('/get/<id>') def get_id(id): if id != '9': abort(404) return '<h1>Hello, %s!</h1>' % id if __name__ == '__main__': app.run(debug=True)

通過訪問可以發現,只有在訪問/get/9時才能正確得到 Hello ,若是輸入其他返回為 404 頁面
abort 不會把控制權交還給調用它的函數,而是拋出異常把控制權交給 Web 服務器

2.6 Flask 擴大

Flask 的開發 Web 服務器支持很多啟動設置選項,但只能在腳本中作為參數傳給 app.run() 函數,這類方式其實不10分方便,傳遞設置選項的理想方式是使用命令行參數。
Flask-Script 是1個 Flask 擴大,為 Flask 程序添加了1個命令行解析器。

from flask import Flask from flask import make_response from flask import redirect from flask import abort from flask.ext.script import Manager app = Flask(__name__) manager = Manager(app) @app.route('/') def index(): response = make_response('<h1>This document carries a cookie!</h1>') response.set_cookie('answer', '42') return response @app.route('/user/<name>') def user(name): return redirect('http://www.baidu.com') @app.route('/get/<id>') def get_id(id): if id != '9': abort(404) return '<h1>Hello, %s!</h1>' % id if __name__ == '__main__': manager.run()

這個擴大的初始化方法為:把程序實例作為參數傳給構造函數,初始化主類的實例。創建的對象可以在各個擴大中使用。在這里,服務器由 manager.run() 啟動,啟動后就可以解析命令行了。
在命令行中啟動試試看:
這里寫圖片描述
Shell 命令用于在程序的上下文中啟動 Python Shell 會話,可以用來運行保護任務或測試,還可以調試異常
runserver 命令用來啟動 Web 服務器

第3章 模版

視圖函數的作用很明確,即生成要求的響應
模版是1個包括響應文本的文件,其中包括用占位符變量表示的動態部份

3.1 Jinja 2 模版引擎

3.1.1 渲染模版

默許情況下,Flask 在程敘文件夾中的 templates 子文件夾中尋覓模版

from flask import Flask from flask import render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') @app.route('/user/<name>') def user(name): return render_template('user.html', name=name) if __name__ == '__main__': app.run()

這段代碼可以和上面實現相同的作用,render_template()函數的第1個參數是模版的文件名,隨后的參數都是鍵值對,表示模版中變量對應的真實值

3.1.2 變量

模版中使用的{{ name }}結構表示1個變量,它是1種特殊的占位符,告知模版引擎這個位置的值從渲染模版時使用的數據中獲得
Jinja2 能辨認所有類型的變量,乃至是1些復雜的類型,例如列表、字典和對象,例如

<p>A value from a dictionary: {{ mydict['key'] }}.</p> <p>A value froma list: {{ mylist[3] }}.</p> <p>A value froma list, with a variable index: {{ mylist[myintvar] }}.</p> <p>A value froman object's method: {{ myobj.somemethod() }}.</p>

下面這個例子就是讀取這些復雜類型的

from flask import Flask from flask import render_template app = Flask(__name__) class Human(): def somemethod(self): return 'Flask say Hello world!' @app.route('/<name>') def user(name): mydict = {"key": "This is a Flask Program"} mylist = ['it', 'Hello', 'the', 'world'] myintvar = 0 myobj = Human() return render_template('user.html', name=name, mydict=mydict, mylist=mylist, myintvar=myintvar, myobj=myobj) if __name__ == '__main__': app.run()

也能夠使用過濾器來修改變量,過濾器名添加在變量名以后,中間使用豎線分隔

過濾器名 說明
safe 渲染值時不轉義
capitalize 把值的首字母轉換成大寫,其他字母轉換成小寫
lower 把值轉換成小寫情勢
upper 把值轉換成大寫情勢
title 把值中的每一個單詞的首字母都變成大寫
trim 把值的首尾空格去掉
striptags 渲染前把值中的 HTML 標簽都刪掉

默許情況出于安全斟酌, Jinja2 會轉義所有變量,完全的過濾器可去 Jinja2 的文檔中查看

3.1.3 控制結構

Jinja2 提供了多種控制結構,可用來改變模版的渲染流程

{{ % if user %}} hello, {{ user }} {{% else %}} hello, world {{% endif % }}

是條件控制結構

{% for comment in comments %} <li>{{ comment }}</li> {% endfor %}

是循環控制結構, Jinja2 還支持宏,宏類似于 Python 代碼中的函數

from flask import Flask from flask import render_template app = Flask(__name__) @app.route('/macro') def macro(): comments = ['it', 'Hello', 'the', 'world'] return render_template('macro.html', comments=comments) if __name__ == '__main__': app.run()

在響應模版macro.html

{% macro render_comment(comment) %} <li>{{comment}}</li> {% endmacro %} <ul> {% for comment in comments%} {{ macro.render_comment(comment) }} {% endfor %} </ul>

奇怪的是這個例子我1直返回的是500毛病,沒有成功
為了提高重用性,可以把重復使用的部份保存在單獨的文件中,在需要使用的模版中導入便可

from flask import Flask from flask import render_template app = Flask(__name__) @app.route('/comments') def comments(): comments = ["it", "Hello", "the", "world"] return render_template('comments.html', comments=comments) if __name__ == '__main__': app.run()

macro.html

{% macro render_comment(comment) %} <li>{{comment}}</li> {% endmacro %}

comments.html

{% import 'macro.html' as macro %} <ul> {% for comment in comments%} {{ macro.render_comment(comment) }} {% endfor %} </ul>

提高重用性的更好方式是模版繼承,就像面向對象中的繼承類似,首先創建1個base.html的基模版

<html> <head> {% block head%} <title> {% block title%}{% endblock%}- My Application </title> {% endblock %} </head> <body> {% block body%} {% endblock%} </body> </html>

衍生模版為child.html

{% extends 'base.html'%} {% block title%} Index {% endblock %} {% block head%} {{ super() }} <style> </style> {% endblock%} {% block body%} <h1>Helll, World!</h1> {% endblock%}

在 Python 文件中

from flask import Flask from flask import render_template app = Flask(__name__) @app.route('/extends') def extends(): return render_template('child.html') if __name__ == '__main__': app.run()

extends指令聲明這個模版衍生自base.html,在此指令后基模版的3個塊被重新定義,模版引擎會將其插入適當的位置,使用super()來獲得原來的內容

3.2 Flask-Bootstrap

from flask.ext.bootstrap import Bootstrap from flask import Flask from flask import render_template app = Flask(__name__) bootstrap = Bootstrap(app) @app.route('/bootstrap/<name>') def bootstrap(name): return render_template('bootstrap.html', name=name) if __name__ == '__main__': app.run()

bootstrap.html

{% extends 'bootstrap/base.html'%} {% block title%} Flasky {% endblock %} {% block navbar%} <div class="navbar navbar-inverse" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">Flasky</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> </ul> </div> </div> </div> {% endblock %} {% block content%} <div class="container"> <div class="page-header"> <h1>Hello, {{ name }}!</h1> </div> </div> {% endblock %}

可以看到,訪問已帶有其他樣式了,這樣就構建了1個“好看”的網頁。Jinja2 中的extends指令從 Flask-Bootstrap 中導入bootstrap/base.html,從而實現模版繼承。Flask-Bootstrap 中的基模版提供了1個網頁框架,引入了 Bootstrap 中的所有 CSS 和 JavaScript 文件
Flask-Bootstrap 的基模版中定義了可在衍生模版中重定義的塊,block 和 endblock 指令定義的塊中的內容可添加到基模版中

塊名 說明
doc 全部 HTML 文檔
html_attribs 標簽中的屬性
html 標簽中的內容
head 標簽中的內容
title 標簽中的內容
metas 1組標簽
styles 層疊樣式表定義
body_attribs 標簽的屬性
body 標簽中的內容
navbar 用戶定義的導航條
content 用戶定義的頁面內容
scripts 文檔底部的 JavaScript 聲明

上表中的很多塊都是 Flask-Bootstrap 自用的,最好不要重新定義,Bootstrap 所需的文件在 styles 和 scripts 塊中聲明,如果程序需要向已有內容的塊中添加新內容,必須使用 Jinja2 提供的super()函數,例如添加1個新的 JavaScript 文件

{% block scripts %} {{ super() }} <script type="text/javascript" src="my-script.js"></script> {% endblock %}

3.3 自定義毛病頁面

from flask.ext.bootstrap import Bootstrap from flask import Flask from flask import render_template app = Flask(__name__) bootstrap = Bootstrap(app) @app.route('/user/<name>') def bootstrap(name): return render_template('bootstrap.html', name=name) @app.errorhandler(404) def page_not_found(e): return render_template('404.html'), 404 @app.errorhandler(500) def internal_server_error(e): return render_template('500.html'), 500 if __name__ == '__main__': app.run()

對已有頁面進行復制粘貼的修改肯定可行
這里寫圖片描述
不過我們想通過更好的方法(模版繼承)來實現,我們定義1個基模版base.html

{% extends "bootstrap/base.html" %} {% block title %}Flasky{% endblock %} {% block navbar %} <div class="navbar navbar-inverse" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/">Flasky</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> </ul> </div> </div> </div> {% endblock %} {% block content %} <div class="container"> {% block page_content %}{% endblock %} </div> {% endblock %}

這個模版的content塊中只有1個

容器,其中包括了1個名為page_content的新的空塊,塊中內容由衍生模版定義,這樣 404.html 就沒必要基于 Flask-Bootstrap 的基模版了,只需要繼承自 base.html 便可。之前的 user.html 也能夠通過這個繼承頁面來進行簡化

{% extends 'base.html'%} {% block title%} 歡迎頁面 {% endblock%} {% block content %} <div class="page-header"> <h1> 歡迎,{{ name }}! </h1> </div> {% endblock%}

3.4 鏈接

Flask 提供了url_for()輔助函數,它可使程序 URL 映照中保存的信息生成 URL
url_for()函數最簡單的用法是以視圖函數名作為參數,返回對應的 URL,

3.5 靜態文件

對靜態文件的援用被當做1個特殊的路由,即/static/<filename>
index.html中加入以下

{% block head %} {{ super() }} <link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}" type="image/x-icon"> {% endblock %}

在網頁查看源碼可以發現,如果存在/static/<filename>即會被加載

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产 | 久而欧洲野花视频欧洲1 | 午夜影院免费版 | 日韩久久久精品中文字幕 | 欧美一级毛片免费观看 | 一级毛片一级毛片a毛片欧美 | 精品国产日韩亚洲一区91 | 99久久久国产精品免费牛牛四川 | 日韩精品久久一区二区三区 | 一区二区影视 | 欧美日韩亚洲一区二区精品 | 亚洲欧美在线观看首页 | 亚洲精品第一页中文字幕 | 国产乱码精品一区二区三上 | 成人在线视频一区 | 这里是九九伊人 | 在线播放亚洲美女视频网站 | 国产国语在线播放视频 | 拍拍拍免费高清在线观看视频 | 成人免费小视频 | 亚洲精品一区二区三区在线播放 | 日韩看片 | 亚欧国产 | www日本视频 | 日韩美女福利视频 | 亚洲欧美综合另类图片小说区 | 亚洲成a人v欧美综合天堂软件 | 欧美 中文字幕 | 中文字幕日韩精品一区口 | 一区二区在线观看视频 | 一级毛片一级毛片一级毛片aaav | 五月综合视频 | 亚洲激情视频在线播放 | 精品国产免费人成在线观看 | 91久久大香伊蕉在人线 | 国产日韩欧美综合一区 | 欧美 日韩 国产在线 | h视频无遮挡免费网站 | 香蕉超级碰碰碰97视频在线观看 | 午夜视频免费在线 | 国产亚洲视频网站 | 亚洲精品国自产拍在线观看 |