課堂筆記

Flask課堂筆記

1. HTTP通信與Web框架

1.1 流程

客戶端將請求打包成HTTP的請求報文(HTTP協議格式的請求數據)

采用TCP傳輸發送給服務器端

服務器接收到請求報文后按照HTTP協議進行解析

服務器根據解析后獲知的客戶端請求進行邏輯執行

服務器將執行后的結果封裝成HTTP的響應報文(HTTP協議格式的響應數據)

采用剛才的TCP連接將響應報文發送給客戶端

客戶端按照HTTP協議解析響應報文獲取結果數據

1.2 細節

客戶端不一定是瀏覽器,也可以是PC軟件、手機APP、程序

根據服務器端的工作,將其分為兩部分:

服務器:與客戶端進行tcp通信,接收、解析、打包、發送http格式數據

業務程序:根據解析后的請求數據執行邏輯處理,形成要返回的數據交給服務器

服務器與Python業務程序的配合使用WSGI協議

1.3 Web框架

能夠被服務器調用起來,根據客戶端的不同請求執行不同的邏輯處理形成要返回的數據的 程序

核心:實現路由和視圖(業務邏輯處理)

1.4 框架的輕重

重量級的框架:為方便業務程序的開發,提供了豐富的工具、組件,如Django

輕量級的框架:只提供Web框架的核心功能,自由、靈活、高度定制,如Flask、Tornado

1.5 明確Web開發的任務

視圖開發:根據客戶端請求實現業務邏輯(視圖)編寫

模板、數據庫等其他的都是為了幫助視圖開發,不是必備的

2. 認識Flask

2.1 簡介

Flask誕生于2010年,是Armin ronacher(人名)用Python語言基于Werkzeug工具箱編寫的輕量級Web開發框架。它主要面向需求簡單的小應用。

Flask本身相當于一個內核,其他幾乎所有的功能都要用到擴展(郵件擴展Flask-Mail,用戶認證Flask-Login),都需要用第三方的擴展來實現。比如可以用Flask-extension加入ORM、窗體驗證工具,文件上傳、身份驗證等。Flask沒有默認使用的數據庫,你可以選擇MySQL,也可以用NoSQL。其 WSGI 工具箱采用 Werkzeug(路由模塊) ,模板引擎則使用 Jinja2 。

可以說Flask框架的核心就是Werkzeug和Jinja2。

Python最出名的框架要數Django,此外還有Flask、Tornado等框架。雖然Flask不是最出名的框架,但是Flask應該算是最靈活的框架之一,這也是Flask受到廣大開發者喜愛的原因。

2.2 與Django對比

django提供了:

django-admin快速創建項目工程目錄

manage.py 管理項目工程

orm模型(數據庫抽象層)

admin后臺管理站點

緩存機制

文件存儲系統

用戶認證系統

而這些,flask都沒有,都需要擴展包來提供

2.3 Flask擴展包:

Flask-SQLalchemy:操作數據庫;

Flask-migrate:管理遷移數據庫;

Flask-Mail:郵件;

Flask-WTF:表單;

Flask-script:插入腳本;

Flask-Login:認證用戶狀態;

Flask-RESTful:開發REST API的工具;

Flask-Bootstrap:集成前端Twitter Bootstrap框架;

Flask-Moment:本地化日期和時間;

2.4 Flask文檔

中文文檔: <u>http://docs.jinkan.org/docs/flask/</u>

英文文檔: <u>http://flask.pocoo.org/docs/0.11/</u>

3. 創建虛擬環境

虛擬環境是一個互相隔離的目錄

  1. mkvirtualenv flask_py2

  2. pip install flask==0.10.1

pip freeze > requirements.txt

pip install –r requirements.txt

4. Flask的Hello world程序

# coding:utf-8

# 導入Flask類
from flask import Flask

#Flask類接收一個參數__name__
app = Flask(__name__)

# 裝飾器的作用是將路由映射到視圖函數index
@app.route('/')
def index():
    return 'Hello World'

# Flask應用程序實例的run方法啟動WEB服務器
if __name__ == '__main__':
    app.run()

4.1 Flask創建app對象

4.1.1 初始化參數

import_name:

static_url_path:

static_folder: 默認‘static’

template_folder: 默認‘templates’

4.1.2 配置參數

app.config.from_pyfile(“yourconfig.cfg”) 或

app.config.from_object()

4.1.3 在視圖讀取配置參數

app.config.get() 或者 current_app.config.get()

4.1.4 app.run的參數

app.run(host=”0.0.0.0”, port=5000)

4.2 路由

4.2.1 app.url_map 查看所有路由

4.2.2 同一路由裝飾多個視圖函數

4.2.3 同一視圖多個路由裝飾器

4.2.4 利用methods限制訪問方式

@app.route('/sample', methods=['GET', 'POST'])

4.2.5 使用url_for進行反解析

4.2.5 動態路由

# 路由傳遞的參數默認當做string處理,這里指定int,尖括號中冒號后面的內容是動態的
@app.route('/user/<int:id>')
def hello_itcast(id):
    return 'hello itcast %d' %id

4.2.5 自定義轉換器

from flask import Flask
from werkzeug.routing import BaseConverter

class Regex_url(BaseConverter):
    def __init__(self,url_map,*args):
        super(Regex_url,self).__init__(url_map)
        self.regex = args[0]

app = Flask(__name__)
app.url_map.converters['re'] = Regex_url

@app.route('/user/<re("[a-z]{3}"):id>')
def hello_itcast(id):
    return 'hello %s' %id

4.3 獲取請求參數

from flask import request

就是 Flask 中表示當前請求的 request 對象,request對象中保存了一次HTTP請求的一切信息。

4.3.1 上傳文件

已上傳的文件存儲在內存或是文件系統中一個臨時的位置。你可以通過請求對象的 files 屬性訪問它們。每個上傳的文件都會存儲在這個字典里。它表現近乎為一個標準的 Python file 對象,但它還有一個 save() 方法,這個方法允許你把文件保存到服務器的文件系統上。這里是一個用它保存文件的例子:

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

如果你想知道上傳前文件在客戶端的文件名是什么,你可以訪問 filename 屬性。但請記住, 永遠不要信任這個值,這個值是可以偽造的。如果你要把文件按客戶端提供的文件名存儲在服務器上,那么請把它傳遞給 Werkzeug 提供的 secure_filename() 函數:

from flask import request
from werkzeug import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
    ...

4.4 abort函數與自定義異常處理

4.4.1 abort函數

from flask import abort

4.4.2 自定義異常處理

@app.errorhandler(404)

def error(e):

return '您請求的頁面不存在了,請確認后再次訪問!%s'%e

4.5 返回的響應數據

4.5.1 元組

可以返回一個元組,這樣的元組必須是 (response, status, headers) 的形式,且至少包含一個元素。 status 值會覆蓋狀態代碼, headers 可以是一個列表或字典,作為額外的消息標頭值。

4.5.2 make_response

resp = make_response()

resp.headers[“sample”] = “value”

resp.status = “404 not found”

4.6 使用jsonify返回json數據

4.5 重定向

from flask import redirect

4.6 設置和讀取cookie

make_response

set_cookie(key, value=’’, max_age=None)

delete_cookie(key)

4.7 session

from flask import session

需要設置secret_key

4.8 請求上下文與應用上下文

請求上下文(request context)

request和session都屬于請求上下文對象。

應用上下文(application context)

current_app和g都屬于應用上下文對象。

current_app:表示當前運行程序文件的程序實例。

g:處理請求時,用于臨時存儲的對象,每次請求都會重設這個變量。

4.9 請求鉤子

請求鉤子是通過裝飾器的形式實現,Flask支持如下四種請求鉤子:

before_first_request:在處理第一個請求前運行。

@app.before_first_request

before_request:在每次請求前運行。

after_request(response):如果沒有未處理的異常拋出,在每次請求后運行。

teardown_request(response):在每次請求后運行,即使有未處理的異常拋出。

5. Flask-Script擴展命令行

pip install Flask-Script

from flask import Flask
from flask_script import Manager

app = Flask(__name__)

manager = Manager(app)

@app.route('/')
def index():
    return '床前明月光'

if __name__ == "__main__":
    manager.run()    ...

6. Jinja2模板

6.1 基本流程

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Template</title>
</head>
<body>
    <h1>hello {{ name }}</h1>
</body>
</html>
@app.route("/")
def index():
    return render_template("index.html", name="python")

使用flask 中的render_template渲染模板

6.2 變量

<p>{{mydict['key']}}</p>

<p>{{mydict.key}}</p>

<p>{{mylist[1]}}</p>

<p>{{mylist[myvariable]}}</p>
from flask import Flask,render_template
app = Flask(__name__)

@app.route('/')
def index():
    mydict = {'key':'silence is gold'}
    mylist = ['Speech', 'is','silver']
    myintvar = 0

    return render_template('vars.html',
                           mydict=mydict,
                           mylist=mylist,
                           myintvar=myintvar
                           )
if __name__ == '__main__':
    app.run(debug=True)

6.3 過濾器

6.3.1 字符串過濾器

safe:禁用轉義;

<p>{{ '<em>hello</em>' | safe }}</p>

capitalize:把變量值的首字母轉成大寫,其余字母轉小寫;

<p>{{ 'hello' | capitalize }}</p>

lower:把值轉成小寫;

<p>{{ 'HELLO' | lower }}</p>

upper:把值轉成大寫;

<p>{{ 'hello' | upper }}</p>

title:把值中的每個單詞的首字母都轉成大寫;

<p>{{ 'hello' | title }}</p>

trim:把值的首尾空格去掉;

<p>{{ ' hello world ' | trim }}</p>

reverse:字符串反轉;

<p>{{ 'olleh' | reverse }}</p>

format:格式化輸出;

<p>{{ '%s is %d' | format('name',17) }}</p>

striptags:渲染之前把值中所有的HTML標簽都刪掉;

<p>{{ '<em>hello</em>' | striptags }}</p>

6.3.2 支持鏈式使用過濾器

<p>{{ “ hello world “ | trim | upper }}</p>

6.3.3 列表過濾器

first:取第一個元素

<p>{{ [1,2,3,4,5,6] | first }}</p>

last:取最后一個元素

<p>{{ [1,2,3,4,5,6] | last }}</p>

length:獲取列表長度

<p>{{ [1,2,3,4,5,6] | length }}</p>

sum:列表求和

<p>{{ [1,2,3,4,5,6] | sum }}</p>

sort:列表排序

<p>{{ [6,2,3,1,5,4] | sort }}</p>

6.3.4 自定義過濾器

自定義的過濾器名稱如果和內置的過濾器重名,會覆蓋內置的過濾器。

方式一:

通過 add_template_filter (過濾器函數, 模板中使用的過濾器名字)

def filter_double_sort(ls):
    return ls[::2]
app.add_template_filter(filter_double_sort,'double_2')

方式二:

通過裝飾器 app.template_filter (模板中使用的裝飾器名字)

@app.template_filter('db3')
def filter_double_sort(ls):
    return ls[::-3]

6.4 表單

使用Flask-WTF表單擴展,可以幫助進行CSRF驗證,幫助我們快速定義表單模板,而且可以幫助我們在視圖中驗證表的數據

pip install Flask-WTF

6.4.1 不使用Flask-WTF擴展時,表單需要自己處理

#模板文件
<form method='post'>
    <input type="text" name="username" placeholder='Username'>
    <input type="password" name="password" placeholder='password'>
    <input type="submit">
</form>
from flask import Flask,render_template,request

@app.route('/login',methods=['GET','POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        print username,password
        return “success”
    else:
        return render_template(“login.html”)

6.4.2 使用Flask-WTF擴展

需要設置 SECRET_KEY 的配置參數

模板頁:

<form method="post">
        #設置csrf_token
        {{ form.csrf_token() }}
        {{ form.us.label }}
        <p>{{ form.us }}</p>
        {{ form.ps.label }}
        <p>{{ form.ps }}</p>
        {{ form.ps2.label }}
        <p>{{ form.ps2 }}</p>
        <p>{{ form.submit() }}</p>
        {% for x in get_flashed_messages() %}
            {{ x }}
        {% endfor %}
 </form>

視圖函數

rf#coding=utf-8
from flask import Flask,render_template, redirect,url_for,session,request,flash

#導入wtf擴展的表單類
from flask_wtf import FlaskForm
#導入自定義表單需要的字段
from wtforms import SubmitField,StringField,PasswordField
#導入wtf擴展提供的表單驗證器
from wtforms.validators import DataRequired,EqualTo
app = Flask(__name__)
app.config['SECRET_KEY']='1'

#自定義表單類,文本字段、密碼字段、提交按鈕
class Login(Flask Form):
    us = StringField(label=u'用戶:',validators=[DataRequired()])
    ps = PasswordField(label=u'密碼',validators=[DataRequired(),EqualTo('ps2','err')])
    ps2 = PasswordField(label=u'確認密碼',validators=[DataRequired()])
    submit = SubmitField(u'提交')

#定義根路由視圖函數,生成表單對象,獲取表單數據,進行表單數據驗證
@app.route('/',methods=['GET','POST'])
def index():
    form = Login()
    if form.validate_on_submit():
        name = form.us.data
        pswd = form.ps.data
        pswd2 = form.ps2.data
        print name,pswd,pswd2
        return redirect(url_for('login'))
    else:
        if request.method=='POST':
flash(u'信息有誤,請重新輸入!')

    return render_template('index.html',form=form)
if __name__ == '__main__':
    app.run(debug=True)

6.5 控制語句

6.5.1 if語句

{% if %} {% endif %}

6.5.2 for語句

{% for item in samples %} {% endfor %}

6.6 宏

類似于python中的函數,宏的作用就是在模板中重復利用代碼,避免代碼冗余。

6.6.1 不帶參數宏的定義與使用

定義:

{% macro input() %}

<input type="text"

     name="username"

     value=""

     size="30"/>

{% endmacro %}

使用

{{ input() }}

6.6.2 帶參數宏的定義與使用

定義

{% macro input(name,value='',type='text',size=20) %}

<input type="{{ type }}"

       name="{{ name }}"

       value="{{ value }}"

       size="{{ size }}"/>

{% endmacro %}

使用

{{ input(value='name',type='password',size=40)}}

6.6.3 將宏單獨封裝在html文件中

文件名可以自定義macro.html

{% macro input() %}

<input type="text" name="username" placeholde="Username">

<input type="password" name="password" placeholde="Password">

<input type="submit">

{% endmacro %}

在其它模板文件中先導入,再調用

{% import 'macro.html' as func %}

{% func.input() %}

6.4 模板繼承

extend

6.5 模板包含

include

6.6 flask在模板中使用特殊變量和方法

6.6.1 config

6.6.2 request

6.6.3 url_for

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容