# Flask框架之視圖和路由


HelloWord程序

創建Python項目

  • 打開Pycharm,創建 pure Python類型的項目,創建項目完成之后選擇之前創建的py3_flask作為虛擬環境


    image.png

第四步路徑可以通過在指定的虛擬環境下,輸入 which python獲得

示例

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


if __name__ == '__main__':
    app.run(debug=True)

第一行:導入Flask類
第三行:Flask函數接收一個參數name,他會指向程序所在的包
第六行:裝飾器的作用是將路由映射到試圖函數hello_word
第十一、十二行: Flask應用程序實例的run方法,啟動WEB服務器

在程序運行過程中,程序實例會使用url_map將裝飾器路由和視圖的對應關系保存起來


相關參數配置

在上一節實現了一個最簡單的 Flask 應用程序,只使用了7行代碼,接來對 Flask 程序的創建,運行配置做進一步的了解,具體有:

  • Flask 程序初始化參數
  • Flask 程序相關配置加載方式
  • app.run() 參數

初始化參數

Flask 程序實例在創建的時候,需要默認傳入當前 Flask 程序所指定的包(模塊),接下來就來詳細查看一下 Flask 應用程序在創建的時候一些需要我們關注的參數:


image.png


  • import_name
    • Flask程序所在的包(模塊),傳 name 就可以
    • 其可以決定 Flask 在訪問靜態文件時查找的路徑
  • static_path
    • 靜態文件訪問路徑(不推薦使用,使用 static_url_path 代替)
  • static_url_path
    • 靜態文件訪問路徑,可以不傳,默認為:/ + static_folder
  • static_folder
    • 靜態文件存儲的文件夾,可以不傳,默認為 static
  • template_folder
    • 模板文件存儲的文件夾,可以不傳,默認為 templates

程序加載配置

在 Flask 程序運行的時候,可以給 Flask 設置相關配置,比如:配置 Debug 模式,配置數據庫連接地址等等,設置 Flask 配置有以下三種方式:

  • 從配置對象中加載(常用)
    • app.config.from_object()
  • 從配置文件中加載
    • app.config.from_pyfile()
  • 從環境變量中加載(了解)
    • app.config.from_envvar()

使用方式

示例:

from flask import Flask


# 1.自定義項目配置類
class Config(object):
    '''flask項目的配置信息,以類屬性的形式羅列即可'''
    DEBUG = True


app = Flask(__name__)

# 方式一:使用類的方式加載項目配置信息
# 2.加載配置類
# app.config.from_object(Config)
# 方式二:使用文件鏈接方式加載項目配置信息
# app.config.from_pyfile('config.ini')
# 方式三:使用環境變量方式
app.config.from_envvar('FLASKCONFIG')


# 常用的項目配置屬性也會在App中保留一份


@app.route('/')
def hello_word():
    return 'Hello Word '


if __name__ == '__main__':
    app.run()

配置對象

  • 從配置對象中加載,創建配置的類,代碼如下:
# 配置對象,里面定義需要給 APP 添加的一系列配置
class Config(object):
    DEBUG = True


# 創建 Flask 類的對象,指向程序所在的包的名稱
app = Flask(__name__)

# 從配置對象中加載配置
app.config.from_object(Config)

運行測試,在修改代碼后直接保存,會自動重啟服務器

配置文件

  • 創建配置文件 config.ini,在配置文件中添加配置


    image.png
  • 使用代碼去加載配置

# 創建 Flask 類的對象,指向程序所在的包的名稱
app = Flask(__name__)

# 從配置文件中加載配置
app.config.from_pyfile('config.ini')

環境變量(了解)

  • 編輯運行的相關配置


    image.png

    image.png
  • 使用代碼去加載
# 創建 Flask 類的對象,指向程序所在的包的名稱
app = Flask(__name__)
# 加載指定環境變量名稱所對應的相關配置
app.config.from_envvar('FLASKCONFIG')

讀取配置

  • app.config.get()
  • 在視圖函數中使用 current_app.config.get()
@app.route('/')
def hello_word():

    # 獲取屬性值
    print(app.config['DEBUG'])
    # 當DEBUG寫錯時,顯示后面的提示信息
    print(app.config.get('DEBUG','AA'))
    return 'Hello Word '

注:Flask 應用程序將一些常用的配置設置成了應用程序對象的屬性,也可以通過屬性直接設置/獲取某些配置:app.debug = True


路由基本定義

  • 明確路由定義的參數,請求方式指定
  • PostMan使用

指定路由地址

# 指定訪問路徑為 demo1
@app.route('/demo1')
def demo1():
    return 'demo1'

給路由傳參實列

有時我們需要將同一類URL映射到同一個視圖函數處理,比如:使用同一個視圖函數來顯示不同用戶的個人信息

# 路由傳遞參數
@app.route('/user/<user_id>')
def user_info(user_id):
    return 'hello %s' % user_id
  • 路由傳遞的參數默認當作string處理,也可以指定參數的類型
# 路由傳遞參數
@app.route('/user/<int:user_id>')
def user_info(user_id):
    return 'hello %d' % user_id

這里指定int,尖括號中的內容是動態的,在此暫時可以理解為接受int類型的值,實際上int代表使用integerConverter去處理url傳入的參數

指定請求方式

在Flask中,定義一個路由,默認的請求方式為:

  • GET
  • OPTIONS(自帶)
  • HEAD(自帶)
    如果想添加請求方式,那么可以如下指定
@app.route('/demo2', methods=['GET', 'POST'])
def demo2():
    # 直接從請求中取到請求方式并返回
    return request.method

完整代示例:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


# 127.0.0.1/demo1
@app.route('/demo1')
def demo1():
    return 'demo1'


# 給路由傳參
# 127.0.0.1:5000/user/str數據類型
# <user_id>轉換器提取url路徑的參數
@app.route('/user/<user_id>')
def demo2(user_id):
    return 'user %s' % user_id


# 127.0.0.1:5000/user_int/int數據類型
@app.route('/user_int/<int:user_id>')
def demo3(user_id):
    return 'user %d' % user_id


if __name__ == '__main__':
    print(app.url_map)
    app.run(debug=True)
    

正則匹配路由

在 web 開發中,可能會出現限制用戶訪問規則的場景,那么這個時候就需要用到正則匹配,根據自己的規則去限定請求參數再進行訪問

具體實現步驟為:

  • 導入轉換器基類:在Flask中,所有的路由的匹配規則都是使用轉換器獨享記錄
  • 自定義轉換器:自定義類繼承與轉換器基類
  • 添加轉換器到默認的轉換器字典中
  • 使用自定義轉化器實現自定義匹配規則

代碼實現

  • 導入轉換器基類
from werkzeug.routing import BaseConverter
  • 自定義轉換器
# 自定義正則轉換器
class RegexConverter(BaseConverter):
    def __init__(self, url_map, *args):
        super(RegexConverter, self).__init__(url_map)
        # 將接受的第1個參數當作匹配規則進行保存
        self.regex = args[0]
  • 添加轉換器到默認的轉換器字典中,并指定轉換器使用時名字為: re
app = Flask(__name__)

# 將自定義轉換器添加到轉換器字典中,并指定轉換器使用時名字為: re
app.url_map.converters['re'] = RegexConverter
  • 使用轉換器去實現自定義匹配規則
    • 當前此處定義規則是:3位數字
@app.route('/user/<re("[0-9]{3}"):user_id>')
def user_info(user_id):
    return "user_id 為 %s" % user_id

運行測試:http://127.0.0.1:5000/user/123 ,如果訪問的url不符合規則,會提示找不到頁面

系統自帶轉換器

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

系統自帶的轉換器具體使用方式在每種轉換器的注釋代碼中有寫,請留意每種轉換器初始化的參數。

完整代碼示例


from flask import Flask
# 導入轉換器基類
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 1.自定義轉換器類
class RegexConverter(BaseConverter):
    # 重寫regex屬性,當你將正則表達式傳入給他的時候,BaseConVerter類處理
    def __init__(self, url_map, re):
        # 1.初始化父類的init方法,完成正則定義注冊工作
        super(RegexConverter, self).__init__(url_map)
        # 2.初始化子類的init方法
        self.regex = re


# 2.注冊正則匹配類
app.url_map.converters['re'] = RegexConverter


@app.route('/')
def hello_word():
    return 'Hello Word'


# 127.0.0.1:5000/user/123456
# 3.使用自定義正則轉換器

@app.route('/user/<re("[0-9]{6}"):user_id>')
def demo1(user_id):
    return 'user %s' % user_id


if __name__ == '__main__':
    app.run(debug=True)
    
    

獲取請求參數

  • request:flask中代表當前請求的 request 對象
  • 作用:在視圖函數中取出本次請求數據
  • 導入:from flask import request
    常用屬性如下:
屬性 說明 類型
data 記錄請求的數據,并轉換為字符 *
form 記錄請求中的表單數據 MultiDict
args 記錄請求中的查詢參數 MultiDict
cookies 記錄請求中的cookie信息 Dict
headers 記錄請求中的報文頭 EnvironHeaders
method 記錄請求使用的HTTP方法 GET/POST
url 記錄請求的URL地址 string
files 記錄請求上傳的文件 *

完整代碼

from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


'''
get: 獲取服務器數據,問號后面攜帶的參數,告知服務器獲取的數據
post: 往服務器新增數據,請求體里面攜帶的參數:一般是需要存到數據庫的數據
'''


# 127.0.0.1:5000/get?user_name=curry&age=18
@app.route('/get')
def demo1():
    """提取get請求問號后面攜帶的參數"""
    # request.method   獲取訪問方式:后面字符串必須大寫
    if request.method == 'GET':
        # 方式: request.method.args.get('key',"")
        user_name = request.args.get('user_name', '')
        age = request.args.get('age', '')
        return '%s %s' % (user_name, age)
    else:
        return '405請求方式不正確'


@app.route('/post', methods=['post'])
def demo2():
    '''提取post請求體中攜帶的參數'''
    if request.method == 'POST':
        # 方式
        user_name = request.form.get('user_name', '')
        user_id = request.form.get('user_id', '')
        return '%s %s' % (user_name, user_id)
    else:
        return '405請求方式不正確'

@app.route('/upload', methods=['post'])
def demo3():

    if request.method == 'POST':
        # 方式:request.files.get('key', '')
        file = request.files.get('pic', '')
        file.save('./1.jpg')
        return 'upload succes'
    else:
        return '405請求方式不正確'

if __name__ == '__main__':
    app.run(debug=True)


構造響應數據

視圖常用邏輯

  • 返回JSON
  • 重定向
    • Url_for
  • 自定義狀態碼

返回JSON

在使用Flask寫一個接口時候需要給客戶端返回JSON數據,在Flask中可以直接使用jsonify生成一個JSON的響應

# 返回JSON
@app.route('/demo3')
def demo3():
    json_dict = {
        "user_id": 10,
        "user_name": "laowang"
    }
    return jsonify(json_dict)

不推薦使用json.dumps轉成JSON字符串直接返回,因為返回的數據要符合HTTP協議規范,如果是JSON需要指定content-type:application/json
完整代碼:

from flask import Flask, jsonify
import json

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


@app.route('/json')
def demo1():
    '''json數據轉換'''

    dict = {
        'name': 'james',
        'age': 34,
        'info': {
            'team': 'laker'
        }
    }
    # 序列化: 將python對象轉換成json字符串
    json_str = json.dumps(dict)
    # 反序列化: 將json字符串轉換成python對象
    my_json = json.loads(json_str)

    # 1.能將python對象轉換成json字符串
    # 2.能將相應體數封裝成響應對象并返回
    # 3.指明了響應數據格式: ContentType = 'application/json'
    my_jsons = jsonify(dict)
    return my_jsons
    # return json_str


if __name__ == '__main__':
    app.run(debug=True)


重定向

  • 重定向到百度
# 重定向
@app.route('/demo4')
def demo4():
    return redirect('http://www.baidu.com')
  • 重定向到自己寫的視圖函數
    • 可以直接填寫自己的Url路徑
    • 也可以使用url_for生成指定試圖函數所對應的url
@app.route('/demo1')
def demo1():
    return 'demo1'

# 重定向
@app.route('/demo4')
def demo4():
    return redirect(url_for('demo1'))
  • 重定向到帶有參數的視圖函數
    • 在url_for函數中傳入參數
# 路由傳遞參數
@app.route('/user/<user_id>')
def user_info(user_id):
    return 'hello %d' % user_id

# 重定向
@app.route('/demo4')
def demo4():
    # 使用 url_for 生成指定視圖函數所對應的 url
    return redirect(url_for('user_info', user_id=100))

完整代碼:

from flask import Flask, redirect, url_for

app = Flask(__name__)


@app.route('/index')
def hello_word():
    return 'Hello Word'


@app.route('/redirect')
def redirects():
    '''重定向到百度'''
    # 使用redirect方法進行重定向
    return redirect('http://www.baidu.com')


@app.route('/demo2')
def demo2():
    '''重定向到自身的根路徑'''

    # url_for : url反向解析函數
    # 根據函數名稱一一解析出對應的url
    return redirect(url_for('hello_word'))


if __name__ == '__main__':
    app.run(debug=True)

自定義狀態碼

  • 在Flask中,可以很方便的返回自定義狀態碼,以實現不符合http協議的狀態碼,例如: status code:666
@app.route('/demo4')
def demo4():
    return '狀態碼為 666', 666

裝飾器路由具體實現梳理

image.png
  • Flask有兩大核心:Werkzeug和Jinja2
    • Werkzeug實現路由\調試和web服務器網關接口
    • Jinja2實現了模板

  • Werkzeug是一個遵循WSGI協議的python函數庫
    • 其內部實現了很多Web框架底層的東西,比如request和response對象;
    • 與WSGI規范的兼容;支持Unicode;
    • 支持基本的會話管理和簽名Cookie;
    • 集成URL請求路由等。

  • Werkzeug庫的 routing 模塊負責實現 URL 解析。不同的 URL 對應不同的視圖函數,routing模塊會對請求信息的URL進行解析,匹配到URL對應的視圖函數,執行該函數以此生成一個響應信息。


    routing模塊內部有:
  • Rule類
    • 用來構造不同的URL模式的對象,路由URL規則
  • Map類
    • 存儲所有的URL規則和一些配置參數
  • BaseConverter的子類
    • 負責定義匹配規則
  • MapAdapter類
    • 負責協調Rule做具體的匹配的工作

狀態保持

  • 因為http是一種無狀態協議,瀏覽器請求服務器是無狀態的。
  • 無狀態:指一次用戶請求時,瀏覽器\服務器無法知道之前這個用戶做過什么,每次請求都是新的請求
  • 無狀態原因:瀏覽器與服務器之間是使用socket套接字進行通信,服務器將請求結果返回給瀏覽器之后,會關閉當前的socket連接,而且服務器也會在處理頁面完畢之后銷毀頁面對象
  • 有時需要保持下來用戶瀏覽的狀態,比如用戶是否登陸過,瀏覽過哪些商品等
  • 實現狀態保存主要有兩種方式
    • 在客戶端保存用cookie
    • 在服務端保存用session

無狀態協議

1.協議對于事務處理沒有記憶能力
2.對同一個 url 請求沒有上下文關系
3.每次的請求都是獨立的,它的執行情況和結果與前面的請求和之后的請求是無直接關系的,它不會受前面的請求應答情況直接影響,也不會直接影響后面的請求應答情況
4.服務器中沒有保存客戶端的狀態,客戶端必須每次帶上自己的狀態去請求服務器
5.人生若只如初見

Cookie

  • Cookie:指某些網站為了辨別用戶身份、進行會話跟蹤而儲存在用戶本地的數據(通常經過加密)。

    • 復數形式Cookies.
    • Cookie是由服務器端生成,發送給客戶端瀏覽器,瀏覽器會將Cookie的key/value保存,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設置為啟用cookie)。
    • Cookie的key/value可以由服務器端自己定義。
  • 提示:

    • Cookie是存儲在瀏覽器中的一段純文本信息,建議不要存儲敏感信息如密碼,因為電腦上的瀏覽器可能被其它人使用
      -Cookie基于域名安全,不同域名的Cookie是不能互相訪問的
      • 如訪問itcast.cn時向瀏覽器中寫了Cookie信息,使用同一瀏覽器訪問baidu.com時,無法訪問到itcast.cn寫的Cookie信息
      • 瀏覽器的同源策略
    • 當瀏覽器請求某網站時,會將本網站下所有Cookie信息提交給服務器,所以在request中可以讀取Cookie信息

設置cookie

from flask imoprt Flask,make_response
@app.route('/cookie')
def set_cookie():
    resp = make_response('this is to set cookie')
    resp.set_cookie('username', 'itcast')
    return resp
image.png

設置過期時間

@app.route('/cookie')
def set_cookie():
    response = make_response('hello world')
    response.set_cookie('username', 'itheima', max_age=3600)
    return response
image.png

獲取cookie

from flask import Flask,request
#獲取cookie
@app.route('/request')
def resp_cookie():
    resp = request.cookies.get('username')
    return resp
image.png

完整代碼:

from flask import Flask, make_response, request

app = Flask(__name__)


@app.route('/')
def hello_word():
    return 'Hello Word'


@app.route('/login')
def login():
    '''登錄成功后借助cookie保存登錄信息'''
    # 1.創建響應對象
    response = make_response('login success')
    # 2.借助響應對象的set_cookie方法設置鍵值對
    '''
    參數1: key   參數2: value  參數3: max_age = 表示過期時長
    '''
    response.set_cookie('user_name', 'laowang', max_age=3600)
    response.set_cookie('user_id', '1', max_age=3600)

    return response


@app.route('/index')
def index():
    '''再次請求首頁的時候,提起cookie中的用戶信息'''
    user_name = request.cookies.get('user_name', '')
    user_id = request.cookies.get('user_id', '')

    return 'index %s  --  %s' % (user_name, user_id)


@app.route('/login_out')
def loginout():
    '''退出登錄刪除cookie中用戶數據'''
    # 1.構建響應對象
    respone = make_response('login out delete')
    # 2.利用響應對象中的delete_cookie方法刪除對應的cookie
    respone.delete_cookie('user_name')
    respone.delete_cookie('user_id')
    return respone


if __name__ == '__main__':
    app.run(debug=True)

Session

  • 對于敏感、重要的信息,建議要存儲在服務器端,不能存儲在瀏覽器中,如用戶名、余額、等級、驗證碼等信息
  • 在服務器端進行狀態保持的方案就是Session
  • Session依賴于Cookie

session數據的獲取

session:請求上下文對象,用于處理HTTP請求中的一些數據內容

@app.route('/set_session')
def set_session():
    session['username'] = 'itcast'
    return 'set_session ok!'

@app.route('/get_session')
def get_session():
    return session.get('username')

記得設置secret_key: app.secret_key = 'password' 的作用
https://segmentfault.com/q/1010000007295395

完整代碼:

from flask import Flask, session

app = Flask(__name__)

# 加密
app.secret_key = 'asdfghjkl'


@app.route('/')
def hello_word():
    return 'Hello Word'


@app.route('/login')
def login():
    '''登錄成功借助cookie儲存用戶登錄信息到服務器'''
    # session 會將用戶數據存儲到服務器中,一般是數據庫
    session['user_name'] = 'laosong'
    session['user_id'] = '1'
    return 'login sucess'


@app.route('/index')
def index():
    '''再次請求首頁的時候可以借助session提取用戶的登錄信息'''
    user_name = session.get('user_name')
    user_id = session.get('user_id')

    return 'user_name : %s, user_id : %s' % (user_name, user_id)


@app.route('/out')
def login_out():
    '''退出后刪除'''
    session.pop('user_name', '')
    session.pop('user_id', '')
    return 'out susser'


if __name__ == '__main__':
    app.run(debug=True)



請求鉤子

在客戶端和服務器交互的過程中,有些準備工作或掃尾工作需要處理,比如:

  • 在請求開始時,建立數據庫連接;
  • 在請求開始時,根據需求進行權限校驗;
  • 在請求結束時,指定數據的交互格式;

為了讓每個視圖函數避免編寫重復功能的代碼,Flask提供了通用設施的功能,即請求鉤子。

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

  • before_first_request
    • 在處理第一個請求前執行
  • before_request
    • 在每次請求前執行
    • 如果在某修飾的函數中返回了一個響應,視圖函數將不再被調用
  • after_request
    • 如果沒有拋出錯誤,在每次請求后執行
    • 接受一個參數:視圖函數作出的響應
    • 在此函數中可以對響應值在返回之前做最后一步修改處理
    • 需要將參數中的響應在此參數中進行返回
  • teardown_request:
    • 在每次請求后執行
    • 接受一個參數:錯誤信息,如果有相關錯誤拋出

完整代碼:

from flask import Flask
from flask import abort

app = Flask(__name__)


# 在第一次請求之前調用,可以在此方法內部做一些初始化操作
@app.before_first_request
def before_first_request():
    print("before_first_request")


# 在每一次請求之前調用,這時候已經有請求了,可能在這個方法里面做請求的校驗
# 如果請求的校驗不成功,可以直接在此方法中進行響應,直接return之后那么就不會執行視圖函數
@app.before_request
def before_request():
    print("before_request")
    # if 請求不符合條件:
    #     return "laowang"


# 在執行完視圖函數之后會調用,并且會把視圖函數所生成的響應傳入,可以在此方法中對響應做最后一步統一的處理
@app.after_request
def after_request(response):
    print("after_request")
    response.headers["Content-Type"] = "application/json"
    return response


# 請每一次請求之后都會調用,會接受一個參數,參數是服務器出現的錯誤信息
@app.teardown_request
def teardown_request(e):
    print("teardown_request")


@app.route('/')
def index():
    return 'index'

if __name__ == '__main__':
    app.run(debug=True)
  • 在第一次請求時打印

before_first_request
before_request
after_request
teardown_request

  • 在第二次請求時打印

before_request
after_request
teardown_request


異常捕獲

HTTP異常主動拋出

  • abort 方法
    • 拋出一個給定狀態的HTTPException 或者 指定響應, 例如想要用一個頁面未找到異常來終止請求,可以調用abort(404)
  • 參數
    • code-HTTP的錯誤狀態碼(必須)
# abort(404)
abort(500)

拋出狀態碼的話,只能拋出 HTTP 協議的錯誤狀態碼

捕獲錯誤

  • errorhandler裝飾器
    • 注冊一個錯誤處理程序,當程序拋出指定錯誤狀態碼的時候,就會調用該裝飾器所裝飾的方法
  • 參數
    • code_or_exception-HTTP的錯誤狀態碼或指定異常
  • 例如統一處理狀態碼為500的錯誤給用戶友好提示:
@app.errorhandler(500)
def internal_server_error(e):
    return '服務器搬家了'
  • 捕獲指定異常
@app.errorhandler(ZeroDivisionError)
def zero_division_error(e):
    return '除數不能為0'

完整代碼:

from flask import Flask, redirect, abort

app = Flask(__name__)


@app.route('/')
def hello_word():
    # 定義兩個錯誤
    # a = 1/0
    # abort 指定錯誤
    abort(404)
    return 'Hello Word'


@app.errorhandler(404)
def handler(e):
    '''404'''
    print(e)
    # 重定向
    return redirect('http://hd.mi.com/webfile/zt/hd/2014042802/cn.html')


@app.errorhandler(ZeroDivisionError)
def error(a):
    '''捕獲異常'''
    return '不能除零'


if __name__ == '__main__':
    app.run(debug=True)


上下文

上下文:即語境,語意,在程序中可以理解為在代碼執行到某一時刻時,根據之前代碼所做的操作以及下文即將要執行的邏輯,可以決定在當前時刻下可以使用到的變量,或者可以完成的事情。

Flask中有兩種上下文,請求上下文和應用上下文

Flask中上下文對象:相當于一個容器,保存了 Flask 程序運行過程中的一些信息。

請求上下文(request context)

在 flask 中,可以直接在視圖函數中使用 request 這個對象進行獲取相關數據,而 request 就是請求上下文的對象,保存了當前本次請求的相關數據,請求上下文對象有:request、session

  • request
    • 封裝了HTTP請求的內容,針對的是http請求。舉例:user = request.args.get('user'),獲取的是get請求的參數。
  • session
    • 用來記錄請求會話中的信息,針對的是用戶信息。舉例:session['name'] = user.id,可以記錄用戶信息。還可以通過session.get('name')獲取用戶信息。

應用上下文(application context)

它的字面意思是 應用上下文,但它不是一直存在的,它只是request context 中的一個對 app 的代理(人),所謂local proxy。它的作用主要是幫助 request 獲取當前的應用,它是伴 request 而生,隨 request 而滅的。

應用上下文對象有:current_app,g

current_app

應用程序上下文,用于存儲應用程序中的變量,可以通過current_app.name打印當前app的名稱,也可以在current_app中存儲一些變量,例如:

  • 應用的啟動腳本是哪個文件,啟動時指定了哪些參數
  • 加載了哪些配置文件,導入了哪些配置
  • 連了哪個數據庫
  • 有哪些public的工具類、常量
  • 應用跑再哪個機器上,IP多少,內存多大
current_app.name
current_app.test_value='value'

g變量

g 作為 flask 程序全局的一個臨時變量,充當者中間媒介的作用,我們可以通過它傳遞一些數據,g 保存的是當前請求的全局變量,不同的請求會有不同的全局變量,通過不同的thread id區別

g.name='abc'

不同的請求,會有不同的全局變量

兩者區別:

  • 請求上下文:保存了客戶端和服務器交互的數據
  • 應用上下文:flask 應用程序運行過程中,保存的一些配置信息,比如程序名、數據庫連接、應用信息等

上下文中的對象只能在指定上下文中使用,超出范圍不能使用 請求上下文和應用上下文原理實現:https://segmentfault.com/a/1190000004223296

完整代碼

from flask import Flask, request, session, current_app, g

app = Flask(__name__)

app.secret_key = 'asdfghjkl'


@app.route('/')
def hello_word():

    # 請求上下文
    print(request.method)
    print(request.url)
    session['user_name'] = 'curry'
    print(session.get('user_name', ''))

    # 應用上下文
    current_app.config.get("DEBUG")
    g.user = 'James'
    print(g.user)

    return 'Hello Word'


if __name__ == '__main__':
    app.run(debug=True)

Flask-script擴展

通過使用Flask-Script擴展,我們可以在Flask服務器啟動的時候,通過命令行的方式傳入參數。而不僅僅通過app.run()方法中傳參,比如我們可以通過:

python hello.py runserver -host ip地址
以上代碼告訴服務器在哪個網絡接口監聽來自客戶端的連接。默認情況下,服務器只監聽來自服務器所在的計算機發起的連接,即localhost連接。

我們可以通過python hello.py runserver --help來查看參數。


image.png

代碼實現

  • 安裝Flask-Script

pip install flask-script

  • 集成Flask-Script
from flask import Flask
from flask_script import Manager

app = Flask(__name__)
# 把 Manager 類和應用程序實例進行關聯
manager = Manager(app)

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

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

Flask-Script 還可以為當前應用程序添加腳本命令,后續項目中會使用到

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

推薦閱讀更多精彩內容

  • flask文檔flask最佳實踐 已經解釋的非常詳細了,我這里只把我關注的點以我的理解記錄一下。 一:程序的基本結...
    m風滿樓閱讀 2,399評論 0 4
  • 這幾天想學新東西,就看了flask框架,本身對python不太了解,網上的很多教程看了,總是在某些地方卡住。翻到一...
    易木成華閱讀 2,262評論 0 11
  • 快速啟動 是不是很渴望馬上開始啊?這篇文檔將會很好的向你介紹Flask。假設你已經安裝好了Flask。如果還沒有安...
    催眠_a363閱讀 699評論 0 1
  • URL和視圖 安裝Homebrew 在終端輸入以下代碼,安裝Homebrew: Python安裝 mac環境下默認...
    云中的Jason閱讀 1,325評論 0 4
  • 兩個核心依賴 falsk主要依賴兩個庫 —— Werkzeug 和 Jinja。 Jinja2 由于大多數Web程...
    SMEB_閱讀 679評論 0 3