Flask簡介與URL和視圖介紹
- 一、虛擬環境介紹
- 1.虛擬環境與全域環境
- 2.為什么需要虛擬環境
- 3.虛擬環境的安裝和簡單操作
- pipenv的安裝
- 創建虛擬環境
- pipfile和pipfile.lock
- 二、Flask介紹
- 1.Flask簡介
- 2.第一個Flask程式
- 三、設定Debug模式
- 四、配置與組態檔
- 1.直接硬編碼
- 2.通過update()方法
- 3.通過from_object()方法
- 4.通過from_pyfile()方法
- 五、URL與函式的映射
一、虛擬環境介紹
1.虛擬環境與全域環境
有時候安裝了一個Python庫,可能在IDE如PyCharm中不能使用,這是因為:
通過pip安裝的庫默認一般在全域環境中,而PyCharm一般會默認創建虛擬環境,所以兩者的環境不一致,導致安裝的包不能正常匯入使用,解決辦法有2種:
- 在PyCharm虛擬環境中安裝庫,使庫位于虛擬環境中
- 將PyCharm的環境設定為全域環境,即我們通常使用的Python,設定為Python的安裝目錄即可
設定示意如下:

2.為什么需要虛擬環境
一般情況下,Python第三方庫安裝是直接通過pip install xxx的方式進行安裝的,這樣安裝會將庫安裝到系統級的Python環境中,
但是有時可能會面臨這樣的問題:如果現在用Django 1.10.x寫了個網站,但是同時有一個Django 0.9開發的專案需要維護,并i企鵝可能Django 1.10不再兼容Django 0.9的一些語法了,這就需要同時擁有Django 1.10和Django 0.9兩套環境,這時候我們就可以通過虛擬環境來解決這個問題,
3.虛擬環境的安裝和簡單操作
虛擬環境管理有很多工具,這里我選擇pipenv,
pipenv的安裝
命令:
- Windows下
pip install pipenv
- Mac下
brew install pipenv
- Linux下
pip install pipenv
創建虛擬環境
安裝之后即可創建虛擬環境,
創建虛擬環境使用命令pipenv shell,如下:

出現圖中所標提示Flask_Framework-rL0Lvhvz及說明安裝成功,此時再運行pip list可以看到虛擬環境中默認安裝的庫:
Package Version
---------- -------
pip 20.0.2
setuptools 46.1.3
wheel 0.34.2
不能同時使用全域環境和虛擬環境的庫,只能選擇使用其中一個,
虛擬環境默認會安裝到系統盤(C盤)下的當前用戶目錄下的 .virtualenvs 目錄下,如果想指定安裝到其他目錄,可以設定系統環境變數,示意如下:

此時再安裝虛擬環境,即會安裝到指定的目錄下,
虛擬環境安裝好之后,需要在PyCharm中設定虛擬環境為當前創建的虛擬環境,即定位選擇虛擬環境下的python.exe檔案,與前面方法相同,
需要在虛擬環境中通過命令pip install flask安裝Flask,再查看安裝的庫,結果如下:
Package Version
------------ -------
click 7.1.1
Flask 1.1.2
itsdangerous 1.1.0
Jinja2 2.11.1
MarkupSafe 1.1.1
pip 20.0.2
setuptools 46.1.3
Werkzeug 1.0.1
wheel 0.34.2
顯然,在安裝flask時,安裝了存在依賴關系的其他庫,
如果電腦中同時擁有Python3和Python2,可以指定版本:
pipenv --three # 泛指Python3的版本
pipenv --two # 泛指Python2的版本
pipenv --python 3.7 # 指定Python具體版本
虛擬環境管理
pipenv shell # 如果虛擬環境已存在則進入虛擬環境,否則創建并進入虛擬環境
exit # 退出虛擬環境
pipenv --rm # 洗掉整個環境 不會洗掉pipfile
pipfile和pipfile.lock
在創建虛擬環境后,虛擬環境目錄下會生成pipfile檔案,內容如下:
[[source]]
name = “pypi”
url = “https://pypi.org/simple”
verify_ssl = true[dev-packages]
[packages]
[requires] python_version = “3.7”
引數說明:
- url
可以指定國內pip源,否則下載庫可能會很慢 - dev-packages
開發環境 - packages
生產環境 - django = “*”
*表示最新版本 - requires
Python版本
pipfile.lock詳細記錄環境依賴,并且使用了Hash演算法以保證完整的對應關系,
如果需要將安裝的庫記錄到Pipfile中,可以使用pip install --dev 庫名將庫安裝到開發環境,
在虛擬環境中運行專案示意run引數:
pipenv run python manage.py runserver
pipenv有一個缺點:
lock不穩定而且時間非常長,所以安裝包的時候記得加上--skip-lock,如下:
pipenv install django --skip-lock
最后開發完成要提交到倉庫的時候再執行pipenv lock命令,
二、Flask介紹
1.Flask簡介
flask是一款非常流行的Python Web框架,誕生于2010年,作者是Armin Ronacher,這個專案最初只是作者在愚人節的一個玩笑,后來由于非常受歡迎,逐漸成為一個正式的專案,
flask自2010年發布第一個版本以來,大受歡迎,深得開發者的喜愛,并且在多個公司已經得到了應用,flask能如此流行的原因,可以分為以下幾點:
- 微框架、簡潔,只做它需要做的,靈活度非常高,給開發者提供了很大的擴展性,
Flask不會幫開發者做太多的決策,一切都可以按照自己的意愿進行更改,- 使用Flask開發資料庫的時候,具體是使用SQLAlchemy還是MongoEngine,選擇權完全掌握在你自己的手中,區別于Django,Django內置了非常完善和豐富的功能,并且如果你想替換成你自己想要的,要么不支持,要么非常麻煩,
- 把默認的Jinija2模板引擎替換成其他模板引擎都是非常容易的,
- Flask和相應的插件寫得很好,
- 開發效率非常高,比如使用SQLAlchemy的ORM操作資料庫可以節省開發者書寫大量sql的時間,
2.第一個Flask程式
from flask import Flask
# 傳入__name__初始化一個Flask實體
app = Flask(__name__)
# 裝飾器,將當前路由映射到指定函式
@app.route('/')
def hello_world():
return 'hello world'
if __name__ == '__main__':
app.run()
列印:
* Serving Flask app "first_flask" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
此時已經創建服務,在瀏覽器中打開http://127.0.0.1:5000/即可看到:

并且在開啟的服務狀態欄下會看到請求的記錄,如:
127.0.0.1 - - [09/Apr/2020 07:54:10] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [09/Apr/2020 07:54:10] "GET /favicon.ico HTTP/1.1" 404 -
說明:
@app.route('/')裝飾器映射URL和執行的函式,這個設定將URL映射到指定的函式上,例中指定當前路由為根目錄,如果為根目錄時也可以不寫 /,但是盡量寫上以示區別,app.run()是讓flask專案運行起來,可以指定主機號和埠號,
默認的host是127.0.0.1,port為5000,host=0.0.0.0可以讓其他電腦也能訪問到該網站,port指定訪問的埠,
三、設定Debug模式
默認情況下flask不會開啟DEBUG模式,開啟DEBUG模式后,flask會在每次保存代碼的時候自動的重新載入代碼,并且如果代碼有錯誤,會在終端進行提示,
在hello_world()函式中加入錯誤代碼進行測驗:
from flask import Flask
app = Flask(__name__)
# 裝飾器,將當前路由映射到指定函式
@app.route('/')
def hello_world():
result = 1 / 0
return 'hello world'
if __name__ == '__main__':
app.run()
重新運行開啟服務后,會發現:

在日志中也會發現報錯:
[2020-04-09 08:07:17,881] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\Lenovo\.virtualenvs\Flask_Framework-rL0Lvhvz\lib\site-packages\flask\app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "xxx/first_flask.py", line 9, in hello_world
result = 1 / 0
ZeroDivisionError: division by zero
127.0.0.1 - - [09/Apr/2020 08:07:17] "GET / HTTP/1.1" 500 -
這與顯然很麻煩,每次修改之后必須重新運行,而且錯誤資訊在日志中才能看到,
我們可以開啟Debug模式,這樣每次修改代碼后都會載入代碼重新運行,并且代碼有問題時會顯示錯誤資訊,
開啟Debug模式有幾種方式:
- 在
run()方法中設定debug引數為True
if __name__ == '__main__':
app.run(debug=True)
- 設定app物件實體的屬性為True
if __name__ == '__main__':
app.debug = True
app.run()
- 通過配置引數config設定
if __name__ == '__main__':
app.config.update(DEBUG=True)
app.run()
config是繼承自字典型別的,所以可以使用字典的update()方法,
開啟Debug模式測驗如下:
from flask import Flask
app = Flask(__name__)
# 裝飾器,將當前路由映射到指定函式
@app.route('/')
def hello_world():
result = 1 / 0
return 'hello world'
if __name__ == '__main__':
app.run(debug=True)
此時再看網頁:

并且控制臺中也會提示已開啟Debug模式:
* Serving Flask app "first_flask" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 313-629-160
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
在開啟了DEBUG模式后,當程式有例外而進入錯誤堆疊模式,第一次點擊某個堆疊想查看變數值的時候,頁面會彈出一個對話框,提示輸入PIN值,比如在剛剛啟動的專案中的PIN值為313-629-160,輸入這個值后,Werkzeug會把這個PIN值作為cookie的一部分保存起來,并在8小時后過期,8小時內不需要再輸入PIN值,這樣做的目的是為了提高安全性,讓除錯模式下的攻擊者更難攻擊到本站,
現在每次修改完代碼保存之后,都會自動加載代碼重啟服務,不需要再手動關閉服務再重啟了,
此時在報錯的網頁中可以Debug,需要使用控制臺提供的PIN,操作示意如下:

Debug模式是在開發環境中開啟的,開發完成上線之后要關閉Debug模式,因為DEBUG模式會帶來非常大的安全隱患,
四、配置與組態檔
Flask專案的配置,都是通過app.config物件來進行配置的,
比如要配置一個專案處于DEBUG模式下,那么可以使用app.config['DEBUG] = True來進行設定,那么Flask專案將以DEBUG模式運行,
在Flask專案中,有四種方式進行專案的配置,
1.直接硬編碼
app = Flask(__name__)
app.config['DEBUG'] = True
硬編碼的方式不靈活,不便于進行復用,
2.通過update()方法
因為app.config是flask.config.Config的實體,而Config類是繼承自dict,因此可以通過update()方法進行配置,
app.config.update(
DEBUG=True,
SECRET_KEY='...'
)
3.通過from_object()方法
如果配置項特別多,可以把所有的配置項都放在一個模塊中,然后通過加載模塊的方式進行配置,假設有一個settings.py模塊,專門用來存盤配置項的,此你可以通過app.config.from_object()方法進行加載,并且該方法既可以接收模塊的的字串名稱,也可以模塊物件,
有兩種形式:
# 1. 通過模塊字串
app.config.from_object('settings')
# 2. 通過模塊物件
import settings
app.config.from_object(settings)
添加組態檔后,將配置項都放入該檔案中,其他檔案直接參考該組態檔中的配置項,提高了代碼的復用性、降低了耦合度,同時,在組態檔中修改了配置項時,其他代碼中均不需要修改,從而提高了代碼的靈活性,
新建config.py檔案,添加一些配置項如下:
# 設定Debug模式為True
DEBUG = True
# 指定HOST
HOST = '127.0.0.1'
在flask檔案中匯入:
from flask import Flask
import config
app = Flask(__name__)
# 裝飾器,將當前路由映射到指定函式
@app.route('/')
def hello_world():
result = 1 / 0
return 'hello world'
if __name__ == '__main__':
app.config.from_object(config)
app.run()
再運行,也能開啟Debug模式,
也可以通過字串形式匯入:
if __name__ == '__main__':
app.config.from_object('config')
app.run()
此時不需要再匯入config模塊,
4.通過from_pyfile()方法
app.config.from_pyfile()方法傳入一個檔案名,通常是以.py結尾的檔案,但也不限于只使用.py后綴的檔案,
通過匯入Python檔案的形式匯入組態檔:
if __name__ == '__main__':
app.config.from_pyfile('config.py')
app.run()
from_pyfile()方法有一個silent引數,設定為True時,如果組態檔不存在也不會報錯;
不僅支持Python格式的組態檔,也支持.ini等格式,
五、URL與函式的映射
從前面的例子中,我們可以看到,一個URL要與執行函式進行映射,使用的是@app.route裝飾器,
@app.route裝飾器中,可以指定URL的規則來進行更加詳細的映射,比如現在要映射一個文章詳情的URL,文章詳情的URL是/article/id/,id有可能為1、2、3…,那么可以通過以下方式:
@app.route('/article/<id>')
def article(id):
return '%s article detail' % id
其中,尖括號是固定語法,表示地址中傳入的引數,默認的資料型別是字串,
如果需要限制引數型別,則要寫成converter:variable,其中converter是型別名稱,可以有以下幾種:
- string
默認的資料型別,接受任何沒有斜杠/的字串, - int
整型, - float
浮點型, - path
和string類似,但是可以傳遞斜杠/, - uuid
uuid型別的字串, - any
可以同時指定多種路徑,
新增路由域函式映射測驗:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '這是我的第一個Flask頁面'
if __name__ == '__main__':
app.run(debug=True)
顯示:

顯然,在地址中訪問http://127.0.0.1/corley可以訪問到,因為在flask中已經定義了,
同時還可以動態傳入引數:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '這是我的第一個Flask頁面'
@app.route('/list/<aid>')
def article_list(aid):
return '這是第{}篇文章'.format(aid)
if __name__ == '__main__':
app.run(debug=True)
顯示:

顯然,因為未定義 /list 所以不能訪問http://127.0.0.1:5000/list;
可以根據傳入的引數動態顯示視圖,但是并未對資料型別進行限制,可以增加對資料型別的限制:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '這是我的第一個Flask頁面'
@app.route('/list/<int:aid>')
def article_list(aid):
return '這是第{}篇文章'.format(aid)
if __name__ == '__main__':
app.run(debug=True)
顯示:

顯然,此時引數只能是整型數字了,
一般情況下引數中不能含有 /,要想含有 /,必須限制為path型別,除了此區別,path與string型別基本一樣,
示例如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '這是我的第一個Flask頁面'
@app.route('/list/<int:aid>')
def article_list(aid):
return '這是第{}篇文章'.format(aid)
@app.route('/list/<path:aid>')
def comment_list(aid):
return '這是第{}個評論'.format(aid)
if __name__ == '__main__':
app.run(debug=True)
顯示:

顯然,如果引數為數字時,匹配article_list(aid)函式,如果為字串型別或者引數中含有 / 時匹配comment_list(aid)函式,
訪問兩個路徑用同一個函式可以用any來限制,示例如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '這是我的第一個Flask頁面'
@app.route('/list/<int:aid>')
def article_list(aid):
return '這是第{}篇文章'.format(aid)
@app.route('/list/<path:aid>')
def comment_list(aid):
return '這是第{}個評論'.format(aid)
@app.route('/<any(notice,follow):url_path>/')
def message(url_path):
return '當前路徑是'.format(url_path)
if __name__ == '__main__':
app.run(debug=True)
顯示:

此時需要在路由路徑最后添加 / 才能正常訪問,
如果不想指定子路徑來傳遞引數,也可以通過 ?= 的形式來傳遞引數,例如:/article?id=xxx,這種情況下,可以通過request.args.get('id')來獲取id的值,如果是post方法,則可以通過request.form.get('id')來進行獲取,
在flask中添加這類的地址引數需要先從flask中匯入request,示例如下:
from flask import Flask
from flask import request
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/corley')
def hello_corley():
return '這是我的第一個Flask頁面'
@app.route('/list/<int:aid>')
def article_list(aid):
return '這是第{}篇文章'.format(aid)
@app.route('/list/<path:aid>')
def comment_list(aid):
return '這是第{}個評論'.format(aid)
@app.route('/<any(notice,follow):url_path>/')
def message(url_path):
return url_path
@app.route('/wd')
def baidu_search():
return request.args.get('keyword')
if __name__ == '__main__':
app.run(debug=True)
顯示:

顯然,如果傳入的引數未在函式中定義,會報錯,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/73543.html
標籤:其他
