中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

什么是Flask框架

發布時間:2020-08-25 15:44:30 來源:億速云 閱讀:240 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關什么是Flask框架,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

一、初識Flask

Flask擴展應用擴展包

二、認識werkzurg,Flask最重要的依賴

Python Web 框架工具包 werkzeug

# 引用werkzurg的功能模塊
from werkzeug.wrappers import Request,Response
from werkzeug.serving import run_simple
# 底層的用法
def run(environ,start_response):
    return [b'abcdefg'] 
if __name__ == '__main__':
    run_simple('localhost',4000,run) # 監聽端口并執行run函數
    # 另一種用法
@Response.application
def hello(request):
    return Response('Hello World!')
    '''
        return到底返回到客戶端什么內容?
        1、狀態碼:status code 200,301,404,返回一個響應的客戶端的狀態碼;
        2、content-type:告訴客戶端用什么方式解析返回的值;
        3、其他的返回頭信息。
    '''
if __name__ == __main__:
    run_simple('localhost',4000,hello)

三、Flask 使用

3.1、簡單的登錄

from flask import Flask as fk , request,render_template as render,redirect,session,make_response
app = fk(__name__)
app.secret_key = 'abckd' # 設置session 的加密值
@app.route('/',methods=['GET','POST'])
def index():
    if request.method == 'POST':
        user = request.form.get('user')
        pwd = request.form['pwd']
        if user == 'admin' and pwd == '123':
            print(user,pwd)
            return '登錄成功!'
    return render('index.html',h2='你好')
    # home.add_url_rule('/',view_func=index) #第二種路由的聲明方式,必須已“/”開頭
if __name__ == '__main__':
    app.run(debug=True,host='192.168.0.11',port=5000) 
'''
執行werkzurg中的run_simple('localhost',4000,hello)
這里只是socket進行了請求監聽,當瀏覽器發起請求后,執行內部的__call__()方法。
'''

3.2、靜態文件的處理方法

<!-- 使用靜態文件需要刪除 <!DOCTYPE html> -->
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/index.css" type="text/css">
    <!-- javascript引用時必須添加type="text/javascript" -->
    <script language="javaacript" src="/statics/jquery.min.js" type="text/javascript"></script> 
    <!-- 推薦使用這樣加載靜態文件 -->
    <link rel="stylesheet" href="{{ url_for('static',filename='index.css') }}" type="text/css"> 
    <!-- url_for(),函數配置靜態文件,一定要在Flask類中設置靜態文件的路徑和別名,藍圖中設置靜態文件路徑和別名是
    不能使用的 -->
</head>
<body>
<h2>index</h2>
<h2>{{ h2 }}</h2>
<form action="/" method="POST">
    <input type="text" name="user" >
    <input type="password" name="pwd">
    <input type="submit" value="提交">
</form>
</body>

使用 url_for 函數獲取靜態資源時,必須在實例化 Flask 對象的時候設置 static_url_path(別名),static_folder(靜態文件路徑)。

from flask import Flask
from .views.index import home
def shb():
    app = Flask(__name__,static_url_path='/static',static_folder='./public',template_folder='./template')
    '''
    PS:
     1、static_folder的路徑一定要設置正確。
     2、static_url_path的值必須是’/static‘,其他測試無效。
     3、url(’static‘,filename='靜態文件路徑') 第一個值必須是’static‘,其他測試無效。
     4、template_folder 配置注意存放路徑。
     5、藍圖中就不再配置存放靜態文件的路徑和引用別名了;模板也不用再配置,這里是全局配置。
    '''
    app.register_blueprint(home,url_prefix="/api")
    return app

3.3、Flask 簡單運用

from flask import Flask,render_template,request,redirect,session
app = Flask(__name__) # __name__ 可以修改為任意字符串,并可以傳入多個參數
app.secret_key = 'abckd' # 設置session加密多余字符串
# 路由裝飾器,必須已“/”開頭
@app.route('/login',methods=['GET','POST'])
# 定義與路由裝飾器匹配的執行函數
def login():
    print(request.method) # request 需要導入,獲取請求的信息
    session['key] = value # 設置session值
    session.get('key') # 獲取session的值
    return render_template('login.html',**{key:value})
    #return render_template('login.html',key=value)
if __name__ == '__main__':
    app.run(url,prot)

3.4、Flask 的實現基礎

Python Threading 線程模塊用法

3.4.1、Threading.local 多線程

作用:為每個線程創建一個獨立的空間,使得線程對自己空間中的數據進行操作(數據隔離)。

import threading
from threading import local
local_obj = local() # 實例化local對象
def task(i):
    local_obj.xxx = i # 為local對象設置一個參數
    print(local_obj.xxx,i) # 獲取local對象中的參數
    # threading.get_ident() 獲取線程的唯一標示
    print(threading.get_ident(),i)
for i in range(10):
    t = threading.Thread(target=task,args(i,)) # 創建線程
    t.start() # 開始執行線程

3.4.2、根據字典自定義類似Threading.localz

import threading
import greenlet # 獲取協程信息
DIC = {}
def task(i):
# 獲取協成的唯一標記
# indent = greenlet.getcurrent()
# treading.get_ident() 獲取線程的唯一標記
    indent = treading.get_ident()
    if indent in DIC:
        DIC[indent]['xxx'] = i
    else:
        DIC[indent] = {'xxx':i}
    print(DIC[index][xxx],i) # 打印字典中的參數
for i in range(10):
    t = threading.Thread(target=task,args=(i,)) # 創建線程
    t.start() # 開始執行線程

3.4.3、自定義升級版Threading.localz

此版本中協程與線程可以完全的兼容,完成對請求的數據隔離。
為什么需要給線程和協程數據進行隔離?
在多個請求的時候,由于每個請求的信息不相同,所以需要對不同的請求信息進行分類管理(數據隔離),從而防止數據混亂;
這樣在需要使用視圖函數取得用戶請求信息的時候,才能根據不同的信息進行取值和修改。
import threading
import time
 
try:
    import greenlet # 獲取協程信息
    get_indent = greenlet.getcurrent
except Exception as e:
    get_indent = threading.get_ident
class local(object):
# DIC={}
    def __init__(self):
   # pass
        object.__setattr__(self,'DIC',{}) # 通過父類的方法設置類屬性
    def __getattr__(self,item):
        indent = get_indent()
        if indent in self.DIC:
            return self.DIC[indent].get(item)
        else:
            return None
    
    def __setattr__(self,key,value):
        indent = get_indent()
        if indent in self.DIC:
            self.DIC[indent][key] = value
        else:
            self.DIC[indent]= {key:value}
    
    obj = local() # 類在實例化的時候運行__init__()方法
  '''
    obj.xx # 對象.方法的時候運行__getattr__()方法,并且把xx當參數傳入
    obj.xx = 123 # 對象.方法賦值的時候運行__setattr__()方法,并且把xx和123當參數傳入
  '''
    def task(i):
        obj.xxx = i
        time.sleep(2)
        print(obj.xxx,i)
    for i in range(10):
        t = threading.Thread(target=task,args=(i,)) # 創建線程
        t.start() # 開始執行線程

3.4.4、Flask簡單執行流程

3.4.4.1、Flask 的基本執行流程

封裝 requestContext 對象, full_dispatch_request(視圖函數 執行), response返回
從app.run() 開始 -->>
Flask的__call__方法-->>
wsgi_app (封裝RequestContext(request,session)對象到 localstack) -->>
full_dispatch_request(視圖函數 執行) -->>
執行擴展(before_request) ,觸發信號 -->>
獲取response -->>
pop reqeust、session -- >>
結束

3.4.4.2、Flask 源碼執行順序

(1)threading local 和 flask的自定義local對象 
        - 基于本地線程 可以實現線程隔離。
(2)請求到來
        封裝  ctx = RequestContext(request,session)
             ctx -- 放入 Local __storage__ { 'id':{stack:[ctx]} }
(3)執行視圖
        導入 request
        print(reqeust) -- >> localproxy __str__
        reqeust.method -- >> localproxy __getattr__
        reqeust + 1 -- >> localproxy __add__    
        調用_lookup_req_object函數,去local中的ctx中獲取reqeust session
(4)請求結束
        ctx.auto_pop
        ctx 從 local 中移除

什么是Flask框架

四、Flask中的方法

Flask request 屬性詳解

# Flask 中的模塊
from flask import Flask,render_template,request,redirect,session
request.method # 獲取請求的方法
request.args # 獲取get請求的數據
request.args.get('') # 獲取get請求指定的值
request.form # 獲取post請求的數據
request.form.get('') # 獲取post請求指定的值
files = request.files.get('') # 獲取POST上傳的文件信息
files.filename # 獲取上傳的文件名
files.stream # 獲取上傳文件的內容
files.save('文件路徑','上傳文件的內容',) # 保存上傳文件到本地
'''
session 的處理 flask 放入的是加密cookie中的,繼承了字典的所有功能;
flask讀取cookie中session對應的值,將該值解密并反序列化成為字典,供視圖函數使用;
當請求結束時,flask會讀取內存中字典的值,進行序列化并加密,寫入到瀏覽器cookie中。
'''
session['key'] = value # 為session賦值 保存在瀏覽器的cookie中
session.get('') # 獲取session的值
del session['key'] # 刪除
# 設置響應頭
rst = make_response('aaa') # 設置返回加密
rst.headers['Access-Control-Allow-Origin'] = '*' # 允許請求的域名
rst.headers['Access-Control-Allow-Methods'] = 'POST' # 允許POST請求
# Flask() 配置項 
import_name, # 文件名稱
static_url_path=None, # 靜態文件別名
static_folder='static', # 靜態文件路徑
static_host=None,
host_matching=False,
subdomain_matching=False,
template_folder='templates', # 模板文件路徑
instance_path=None, # 實例文件路徑
instance_relative_config=False, # 實例配置文件相對路徑
root_path=None # 根文件路徑
# Flask 配置文件 app.config['ENV'] 獲取內部的值
'ENV':                        None,
'DEBUG':                       None,
'TESTING':                     False,
'PROPAGATE_EXCEPTIONS':             None,
'PRESERVE_CONTEXT_ON_EXCEPTION':       None,
'SECRET_KEY':                   None,
'PERMANENT_SESSION_LIFETIME':         timedelta(days=31), # session保留時間
'USE_X_SENDFILE':                 False,
'SERVER_NAME':                   None, # 設置域名 xxx.com
'APPLICATION_ROOT':               '/',
'SESSION_COOKIE_NAME':             'session',
'SESSION_COOKIE_DOMAIN':            None,
'SESSION_COOKIE_PATH':             None,
'SESSION_COOKIE_HTTPONLY':           True,
'SESSION_COOKIE_SECURE':            False,
'SESSION_COOKIE_SAMESITE':           None,
'SESSION_REFRESH_EACH_REQUEST':       True, # session以什么方式保存保留時間
'MAX_CONTENT_LENGTH':              None, # 上傳文件大小限制
'SEND_FILE_MAX_AGE_DEFAULT':         timedelta(hours=12),
'TRAP_BAD_REQUEST_ERRORS':           None,
'TRAP_HTTP_EXCEPTIONS':             False,
'EXPLAIN_TEMPLATE_LOADING':          False,
'PREFERRED_URL_SCHEME':             'http',
'JSON_AS_ASCII':                 True,
'JSON_SORT_KEYS':                 True,
'JSONIFY_PRETTYPRINT_REGULAR':        False,
'JSONIFY_MIMETYPE':               'application/json',
'TEMPLATES_AUTO_RELOAD':            None,
'MAX_COOKIE_SIZE': 4093,
'SQLALCHEMY_DATABASE_URI' :                'mysql://root:root@127.0.0.1/mysql', # 配置數據庫連接
'SQLALCHEMY_TRACK_MODIFICATIONS' :         False,
# 自定義配置
'SERVER_PORT':                             8000, # 端口
'IP_PATH':                                 '127.0.0.1',# 訪問鏈接
# 綁定二級域名的方法
app.url_map.default_subdomain = 'www' # 設置域名前綴
app.config['SERVER_NAME'] = 'testing.com' # 設置域名
app.register_blueprint(public, subdomain='static') # 設置靜態文件
PS:要指定默認的域名(app.url_map.default_subdomain ),不然無法訪問;
    SERVER_NAME、app.url_map.default_subdomain 在開發環境是不能加,會報404。

五、Flask配置文件

5.1、通過字符串獲取 Class 并運行(反射)

hasattr、setattr、getattr 解釋

hasattr(object, name) 判斷一個對象里面是否有name屬性或者name方法,返回BOOL值,有name特性返回True, 否則返回False。

class test():
    name="xiaohua"
    def run(self):
        return "HelloWord"
t=test()
hasattr(t, "name") #判斷對象有name屬性
#輸出:True
hasattr(t, "run")  #判斷對象有run方法
#輸出:True

setattr(object, name, values) 給對象的屬性賦值,若屬性不存在,先創建再賦值。

getattr(object, name[,default]) 可以取出來某個屬性,這個屬性如果是一個字段,就得到字段的值了,如果是一個方法,就得到這個方法的指針了,然后可以根據方法的指針來調用方法。

class test():
    name="xiaohua"
    def run(self):
        return "HelloWord"
t=test()
setattr(t,'max',30) #在對象中設置max屬性
getattr(t, "name") #獲取name屬性,存在就打印出來。
#輸出:'xiaohua'
getattr(t, "run")  #獲取run方法,存在就打印出方法的內存地址。
#輸出:<bound method test.run of <__main__.test instance at 0x0269C878>>
getattr(t, "run")()  #獲取run方法,后面加括號可以將這個方法運行。
#輸出:'HelloWord'
getattr(t, "age")  #獲取一個不存在的屬性。
'''
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: test instance has no attribute 'age'
'''
getattr(t, "age","18")  #若屬性不存在,返回一個默認值。
#輸出:'18'

5.2、Flask配置文件的原理

# settings.py 文件
class Foo(object):
    DEBUG = True
# 獲取settings.py中類的項目
import importlib
path = 'settings.Foo'
p,c = path.rsplit('.',maxsplit=1)
m = importlib.import_module(p)
cls = getattr(m,c)
# 如果找到這個類
for key in dir(cls):
    if key.isupper():
        print(key,getattr(cls,key))
# 輸出
# DEBUG True

5.3、Flask 三種加載配置方式

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

從配置對象中加載(常用):app.config.from_object()

從配置文件中加載:app.config.from_pyfile()

從環境變量中加載(了解):app.config.from_envvar()

以下演練以設置應用程序的 DEBUG(調試模式) 為例,設置應用為調式模式這后,可以實現以下功能。

5.3.1、配置文件

創建配置文件 config.py,在配置文件中添加配置。

app.config.from_pyfile('config.py')

5.3.2、環境變量(了解)

加載指定環境變量名稱所對應的相關配置

app.config.from_envvar('FLASKCONFIG')
# 讀取配置
app.config.get()

在視圖函數中使用 current_app.config.get() 注:Flask 應用程序將一些常用的配置設置成了應用程序對象的屬性,也可以通過屬性直接設置/獲取某些配置:app.debug = True

5.3.3、Flask配置文件的原理

# settings.py 文件
class Foo(object):
    DEBUG = True
# 獲取settings.py中類的項目
import importlib
path = 'settings.Foo'
p,c = path.rsplit('.',maxsplit=1)
m = importlib.import_module(p)
cls = getattr(m,c)
# 如果找到這個類
for key in dir(cls):
    if key.isupper():
        print(key,getattr(cls,key))
# 輸出
# DEBUG True

5.4、配置對象加載配置

'''
 app.config # 獲取配置文件對象
 app.config['ENV'],app.config['ENV'] = ‘aaa'  # 獲取和設置配置文件的值
 app.config.from_object(‘settings.Foo’)  # 通過外部文件引入配置文件
'''
 # settings.py 文件
 class 類名:
 配置文件key = 配置文件value
 # 使用 settings.py 文件,文件名任意。
 app.config.from_object(‘settings.類名’)
# 主程序運行文件
from flask import Flask
from .views.account import  bpaccount # 導入視圖
from .views.code import bpcode
app = Flask(__name__)
app.config.from_object("settings.TestingConfig") #導入配置文件配置類
# 讀取配置文件 app.config['DEBUG']
def create_app():
    app=Flask(__name__)
    app.config.from_object("settings.DevelopmentConfig")#導入配置文件配置類
    app.register_blueprint(bpaccount)
    app.register_blueprint(bpcode)
    return app
# settings文件
class Config(object): # 公共的配置類
    DEBUG =False
    SECRET_KEY="ADAFA"
    
# 不同應用環境的不同配置類
class ProductionConfig(Config):
    DEBUG = False
class DevelopmentConfig(Config):
    DEBUG = False
class TestingConfig(Config):
    TESTING=True

六、路由系統

6.1、endpoint 的使用

from flask import Flask, url_for
app = Flask(__name__)
 # endpoint 根據名字反向生成URL '/index' 。如果不設置默認為函數名 url_for( 'index')
@app.route('/home',methods=['GET'],endpoint='n1')
def index():
    print(url_for('n1',name=124)) # 反向生成的URL
    return 'Index'
# app.add_url_rule('/home',view_func=index,methods=['GET'],endpoint='n1') # 第二種定義路由的方法
if __name__ == '__main__':
    app.run(debug=True) # 修改自動重啟Flask
'''
 url_for('n1',name=124)
 輸出:/home?name=124
'''

6.2、路由傳參

 '''
  動態路由:
   /index/<int:nid> 只接收整數
   /index/<float:nid> 接收浮點數
   /index/<name> 接收字符串,自定義
   /index/默認為字符串 
 '''
from flask import Flask,request,render_template as render,redirect,session,make_response as response,url_for
app = Flask(__name__,static_url_path='/static/')
@app.route('/<int:nid>',methods=['GET','POST'])
# @app.route('/<aname>/<int:aid>',methods=['GET','POST'])
def index(nid):
    print(url_for('index',nid=777))
 # print(url_for('index.n1',aname=aname,aid=aid))
    if request.method == 'POST':
        user = request.form.get('user')
        pwd = request.form.get('pwd')
    if user == 'admin' and pwd == '123':
        return render('index.html',success='提交成功!')
        return render('index.html',h2='首頁')
    if __name__ == '__main__':
        app.run()
 '''
 輸出:/index/777
 '''

6.3、 route() 參數

rule # URL規則
view_func # 視圖函數名稱
methods=['GET'] # 請求的方式
endpoint=None # 名稱用于反向生成URL,即:url_for('名稱')
strict_slashes=None # 對URL最后的 ‘/’ 符號是否嚴格要求 True:嚴格要求 False:不嚴格要求
redirct_to='/new/<int:nid>' # 重定向
 
    app.config['SERVER_NAME'] = ‘主域名’
    subdomain='url' # 配置主域名下子域名訪問地址,寫入'<username>'表示任意子域名

6.4、自定義正則

from flask import Flask,render_template as render,url_for
from werkzeug.routing import BaseConverter
app = Flask(__name__,static_url_path='/static',static_folder='static')
# 自定義正則轉換器
class RegexConverter(BaseConverter):
    def __init__(self, map, *args):# map 路由傳入的路徑集合
        super(RegexConverter, self).__init__(map)
        # 將接受的第1個參數當作匹配規則進行保存
        self.regex = args[0]
    def to_python(self, value):# 正則匹配URL時觸發
        return int(value) # value為匹配到的值
    def to_url(self, value): # 方向生成URL觸發
        val = super(RegexConverter, self).to_url(value)
        return val # url_for() nid 的值
# 將自定義轉換器添加到轉換器字典中,并指定轉換器使用時名字為: reg
app.url_map.converters['reg'] = RegexConverter
@app.route('/<reg("\d+"):nid>',methods=['GET','POST'])
def index(nid):
    print(url_for('index',nid=222))
    return render('index.html',h2='index')
if __name__ == '__main__':
    app.run()

6.5、瀏覽器請求URL,Flask視圖函數訪問流程

6.5.1、循環引用的執行流程

什么是Flask框架

6.5.2、找不到視圖函數的解釋

為什么循環引用后,無法找到視圖函數?

在上圖中執行流程中執行了兩次 app = Flask(__name__),第一次在fisher主執行流程時,app被賦值一次,但是在book引用fisher主執行文件以后再次執行了 app = Flask(__name__),這樣fisher主執行流程的app被后執行的book引用app所覆蓋,所以當book引用中流程執行到 if 跳到主執行流程繼續執行時, app 已經是 book 模塊的賦值,因此就會找不到視圖函數。

可以通過 id() 打印app的內存地址來查看兩個app是否是同一個app。

七、FBV 視圖

FBV 視圖:利用函數與路由建立關聯,實現請求響應的控制。 CBV 視圖:通過定義類的方式來建立視圖與路由的關聯。

# CBV視圖
from flask import Flask,views
app = Flask(__name__,static_url_path='/static',static_folder='static')
class UserViews(views.MethodView):
    methods = ['GET'] # 設置請求方式
    decorators = [] # 設置裝飾器(全部) 
    def get(self,*args,**kwargs):
        return 'GET'
    def POST(self,*args,**kwargs):
        return 'POST'
app.add_url_rule('/index',None,UserViews.as_view('uuu'))
if __name__ == '__main__':
    app.run()

7.1、請求相關request

下面是request可使用的屬性,其中'*'是比較常用的。
*form 
一個從POST和PUT請求解析的 MultiDict(一鍵多值字典)。
*args 
MultiDict,要操作 URL (如 ?key=value )中提交的參數可以使用 args 屬性:
searchword = request.args.get('key', '')
*values 
CombinedMultiDict,內容是form和args。 
可以使用values替代form和args。
*cookies 
顧名思義,請求的cookies,類型是dict。
stream 
在可知的mimetype下,如果進來的表單數據無法解碼,會沒有任何改動的保存到這個·stream·以供使用。
很多時候,當請求的數據轉換為string時,使用data是最好的方式。這個stream只返回數據一次。
*headers 
請求頭,字典類型。
*data 
包含了請求的數據,并轉換為字符串,除非是一個Flask無法處理的mimetype。
*files 
MultiDict,帶有通過POST或PUT請求上傳的文件。
environ 
WSGI隱含的環境配置。
*method 
請求方法,比如POST、GET。
path
.script_root
.url
.base_url
.url_root 
如果用戶請求如下URL: 
http://www.example.com/myapplication/page.html?x=y

以上的參數內容如下:

什么是Flask框架

is_xhr 
如果請求是一個來自JavaScript XMLHttpRequest的觸發,則返回True,這個只工作在支持
X-Requested-With頭的庫并且設置了XMLHttpRequest。
blueprint 
藍本名字。
endpoint 
endpoint匹配請求,這個與view_args相結合,可是用于重構相同或修改URL。當匹配的時候發生異常,會返回None。
get_json(force=False, silent=False, cache=True)
json 
如果mimetype是application/json,這個參數將會解析JSON數據,如果不是則返回None。 
可以使用這個替代get_json()方法。
max_content_length 
只讀,返回MAX_CONTENT_LENGTH的配置鍵。
module
如果請求是發送到一個實際的模塊,則該參數返回當前模塊的名稱。這是棄用的功能,使用blueprints替代。
on_json_loading_failed(e)
routing_exception = None 
如果匹配URL失敗,這個異常將會/已經拋出作為請求處理的一部分。這通常用于NotFound異常或類似的情況。
url_rule = None 
內部規則匹配請求的URL。這可用于在URL之前/之后檢查方法是否允許(request.url_rule.methods) 等等。 
默認情況下,在處理請求函數中寫下 print('request.url_rule.methods', request.url_rule.methods) 
會打印:
request.url_rule.methods {‘GET’, ‘OPTIONS’, ‘HEAD’}
view_args = None 
一個匹配請求的view參數的字典,當匹配的時候發生異常,會返回None。

7.2、響應相關

from flask import Flask,make_response as response,jsonify,render_template as render,redirect
'''
    make_response 封裝所有形式的返回響應體,并可以設置返回響應頭
    res = response(render('index.html',**{'k1':'v1'}))
    return res
    返回響應體
    return '' 返回字符串
    return jsonify({'k1':'v1'}) 返回json字符串
    return render('index.html',**{'k1':'v1'}) 返回一個文件
    return redirect('http://www.baidu.com') 返回重定向URL
'''
app = Flask(__name__,static_url_path='/static/')
app.secret_key = 'abck'
@app.route('/',methods=['GET','POST'])
def index():
    res = response('index.html')  # 封裝了返回字符串響應體
    res.headers['xxx'] = 123 # 設置返回響應頭
    res.set_cookie = 321 # 設置cookies
    return res # 返回請求體,請求頭,
if __name__ == '__main__':
    app.run()

7.3、before_request 裝飾器

from flask import Flask,make_response as response,jsonify,render_template as render,redirect,request
app = Flask(__name__,static_url_path='/static/')
# app.before_request后面的函數,在所有函數執行前執行。
# app級中app.before_request(函數名)直接使用。
# 藍圖中使用裝飾器的方式
@app.before_request 
def func():
 if request.path == '/index':
   return None
 return '返回值'
  # 返回值不是None,不再往后執行,直接返回return的值
  # 返回None,才往后執行其他,這里執行index函數
 
@app.route('/',methods=['GET','POST'])
def index():
 res = response('index.html')  # 封裝了返回字符串響應體
 res.headers['xxx'] = 123 # 設置返回響應頭
 res.set_cookie = 321 # 設置cookies
 return res # 返回請求體,請求頭,
 
if __name__ == '__main__':
 app.run()

八、模板渲染

Flask 模板詳解

8.1、基本語句的使用

# 字符串,字典,列表等基本數據類型,都可以通過python本來的方法操作。
{{ 屬性名.0 }}
{{ 屬性名[0] }}
{{ 屬性名() }}
 
# html標簽轉換
{{ html標簽|safe }}
from flask import Markup
Markup('<h2>h2標簽</h2>')
# 設置默認
{{ 屬性名|default('你好') }}

8.2、設置全局模板函數

# 設置全局所用的函數
@app.template_global()
def sb(a1,a2):
    return a1 + a2
# 使用:{{ sb(a1,a2) }}
 
# 過濾filter 的使用
@app.template_filter()
def sb(a1,a2,a3):
    return a1 + a2 + a3
# 使用:{{ a1|sb(a2,a3) }}

8.3、模板的繼承

模塊:{% block content %}{% endblock %}
模板文件:
 <html>
<head>
    <meta charset="UTF-8">
    <title>首頁</title>
    <link rel="stylesheet" href="{{ url_for('static',filename='index.css') }}" type="text/css">
</head>
<body>
    <div>
        {% block content %}{% endblock %}
        <a href="{{ url_for('admin.index',id=1234)}}">url_for跳轉帶參數</a>
    </div>
</body>
 </html>
----------------------------------------------------------------------------------------
 <!-- 導入模板文件 -->
 {% extends './template.html' %}
 {% block content %}
  <h2> 你好 </h2>
    {{ h2 }}
 {% endblock %}
調用模塊:
需要使用模塊文件的引入: 
{% extents '模板文件' %} 
模塊代碼:
{% block content %}
<h2> 你好 </h2>
{{ h2 }}
{% endblock %}
-------------------------------------------------------------------------------------
導入模板:{% include '模板文件' %}
 
宏定義:{% macro ccc(name,type='text',value='') %} # 相當于定義def 函數
<input type="{{ type }}" name="{{ name }}"/>
<input type="submit" value="提交"/>
{% endmacro %}
使用宏:{{ ccc('n1') }}

8.4、url_for生成靜態文件URL連接

'''
# 常規構造靜態文件鏈接 
1.包含可變部分的動態路由,url_for(endpoint,_external=True,**kwargs)以視圖函數端點名和可選參數作為參數,
  當_external為True時返回url絕對路徑,否則返回相對路徑
2.url_for(endpoint,_external=True,**kwargs)中可以為動態靜態文件部分傳遞參數,
  如url_for('.static',_external=True,filename='js/html5shiv.min.js'),
  返回的url是http://localhost/static/js/html5shiv.min.js
'''
# 不在藍圖中使用 url_for 構建靜態文件路徑 
# http://localhost/static/js/fixes/html5shiv.min.js 
print url_for('static', filename='js/fixes/html5shiv.min.js', _external=True)
'''
PS:藍圖中endpoint必須加上當前命名空間前綴表示當前命名空間,如定義的main藍圖,必須如下使用
url_for('main.static',_external=True,filename='js/html5shiv.min.js')
'''
# 藍圖中使用url_for構建反向連接時必須添加藍圖名
# http://localhost/static/js/fixes/html5shiv.min.js 
print url_for('.static', filename='js/fixes/html5shiv.min.js', _external=True)
print url_for('main.static', filename='js/fixes/html5shiv.min.js', _external=True)

8.5、錯誤頁面設置

定義錯誤頁面用裝飾器 @app.errorhandler() 來完成,在定義的過程中必須遵循的是在 Flask 直接實例化下定義,不然會定義不成功。

# _*_ coding:utf-8 _*_
from flask import Flask, render_template as render
app = Flask(__name__)
@app.errorhandler(404)
def page_not_found(error):
    return render('/home/404.html'), 404

九、Flash和特殊裝飾器

9.1、flash 消息閃現

在使用 flash() 時會使用到session,所以需要在配置文件中配置 SECRET_KEY。

from flask import flash,get_flashed_messages
flash('',category='數據分類屬性') # 設置
flash('Error',category='error') 
get_flash_messages() # 獲取
get_flash_messages(category_filter=['數據分類屬性']) # 通過分類獲取
'''
flash 實現原理:
    flash基于session來處理內容,先將flash('')中的值存入session中,再通過session的pop移除,達到用一次就消失的效果。
'''
# session自己實現
session.pop('屬性名')

HTML中獲取 flash() 信息

在模板引擎中怎樣定義一個變量;通過關鍵字 set 定義一個變量。category_filte 過濾返回的類別。

{% set messages = get_flash_messages(category_filter=["error"]) %}

Flask消息閃現文檔

9.2、Flask中間件

9.2.1、特殊裝飾器

#設置全局模板函數
@template_global()
@template_filter()
# app.route視圖函數執行前執行,只運行第一次
@app.before_first_request
def x1():
    print('before_first')

# app.route視圖函數執行前執行,多個誰先定義誰先執行
@app.before_requesr
def x2():
    print('before')

# app.route視圖函數執行后執行,必須有參數和返回值,多個誰后定義誰先執行
@app.after_request
def x3(response):
    print('after')
return response

#定義404
@app.errorhandler(404) 
def not_fourd(arg):
    return '404'

9.2.2、中間件

 '''
  Flask的中間件需要通過自定義方法,去替換源碼中的相關方法,利用在程序獲得請求時才運行__call__()的特性,
  來創建中間件,從而完成中間件的功能。
 '''
class Middleware(object):
 def __init__(self, old):
     self.old = old
 def __call__(self, *args, **kwargs):
     print('前')
     ret = self.old(*args, **kwargs)
     print('后')
     return ret
   
if __name__ == '__main__':
    app.wsgi_app = Middleware(app.wsgi_app)

十、藍圖

為開發者提供一個目錄結構,讓開發更規范,可以將特殊裝飾器加到藍圖中,并根據不同的返回內容設置不同的域名前綴。

為什么flask的根目錄不是第一個flask03,而是第二個flask03?

因為在對 Flask(__name__) 進行實例化時,__name__ 所獲取的值決定了Flask根目錄的位置。

10.1、藍圖的基本模型

什么是Flask框架

10.1.1、主路由視圖函數

__init__.py

from flask import Flask
# 導入定義的藍圖模塊
from .views.index import n
def app_view():
    app = Flask(__name__,)
    # 注冊,url_prefix指定打開URL的訪問集 http://127.0.0.1/app/1 http://127.0.0.1/app/2 
    app.register_blueprint(n,url_prefix='/app')# 添加了url_prefix 模板文件靜態文件也需要添加'/app'
    return app

app.py

from flask03 import app_view
app = app_view()
print(app)
if __name__ == '__main__':
    app.run()

10.1.2、分路由視圖函數

index.py

#coding:utf8
from flask import Blueprint
# ps:藍圖名不能與視圖函數名一致
n = Blueprint('index',__name__,template_folder='../xxx',
static_folder='../statics',static_url_path='/statics')
'''
 在藍圖中,必須帶上“藍圖函數.endpoint名”
 url_for('index.n1',name=name)
 url_for('.n1',name=name)
'''
@n.route('/home/<name>',methods=['GET'],endpoint='n1')
def index(name):
    print(name)
    print(url_for('index.n1',name=name))
    return 'home'
'''
 訪問域名:http://127.0.0.1:5000/api/home/123
 輸出:“name”:123
    “url_for('index.n1',name=name)”:/api/home/123
'''

10.2、大項目藍圖目錄結構

什么是Flask框架

十一、Flask上下文管理

11.1、Flask執行順序

上下文管理的內容:
request、session、app、g
1、客戶端請求到來時,會將request/session封裝到一個對象 RequestContext(self,environ)中(其中self為app對象,
environ為客戶端請求的原始數據);
ctx=RequestContext(self,environ) 封裝了 request/session 
2、將含有request/session的對象打包,根據線程/協程的唯一標識,作為字典存放在一個
“空間中”(線程/協程唯一標識作為Key,RequestContext對象作為Value),
{
線程/協程唯一標識:{ctx:RequestContext對象}
....
}
3、視圖函數運行過程
from flask import request,session
request.method
當有請求過來時,通過線程/協程唯一標識找到,存放在空間中的RequestContext對象,再通過對象找到封裝其中的
request/session,最后找到屬性.method。
4、請求結束
session保存到瀏覽器cookie中,并移除字典中的數據,從而結束請求。

11.2、偏函數

import functools
def index(a1,a2):
    return a1+a2
# 函數常規的用法
a = index(12,20)
print(a)
'''
 利用 functools 模塊實現偏函數;
 偏函數只要傳入一個值,其他的值自動傳入
'''
new_func = functools.partial(index,666)
a1 = new_func(34)
print(a1)

11.3、上下文:執行流程

request 請求執行流程

什么是Flask框架

11.4、上下文session

Flask session 的請求流程

十二、Flask 中的 localProxy 方法

local:維護保存在__storage__字典中的線程/進程;

localStack:視圖系統通過其操作local維護的__storage__字典;

localProxy:它的作用主要是幫助 request 獲取當前應用的HTTP請求信息,伴 request 運行和消失的。

class LocalProxy(object):
    def __init__(self):
        pass
    def __getattr__(self):
        pass
    def __setattr__(self):
        pass
    def __getitem__(self):
        pass

lp = LocalProxy()

十三、Flask g變量

1、g作為flask程序全局的一個臨時變量,充當著中間媒介的作用,我們可以通過它傳遞一些數據;

2、g保存的是當前請求的全局變量,不同的請求會有不同的全局變量,通過不同的thread id區別;

3、g對象在一次請求中的所有代碼任何地方,都是可以使用的。

g.name='abc'

g變量簡單應用

1、創建一個utils.py文件,用于測試除主文件以外的g對象的使用

# utils.py
#encoding: utf-8
from flask import g
def login_log():
    print u'當前登錄用戶是:%s' % g.username
def login_ip():
    print u'當前登錄用戶的IP是:%s' % g.ip

2、在主文件中調用utils.py中的函數

#encoding: utf-8
from flask import Flask,g,request,render_template
from utils import login_log,login_ip
app = Flask(__name__)
 
@app.route('/')
def hello_world():
    return 'Hello World!'
    
@app.route('/login/',methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
username = request.form.get('username')
password = request.form.get('password')
g.username = username
g.ip = password
login_log()
login_ip()
return u'恭喜登錄成功!'
 
if __name__ == '__main__':
    app.run()

關于什么是Flask框架就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新兴县| 高青县| 西畴县| 清流县| 土默特右旗| 江城| 琼结县| 伊宁市| 开江县| 武胜县| 五常市| 东港市| 沂水县| 威信县| 专栏| 陆河县| 腾冲县| 大同市| 会同县| 江华| 张家口市| 苍南县| 故城县| 安新县| 柳林县| 唐海县| 伽师县| 布尔津县| 定日县| 蒲城县| 乐陵市| 方山县| 图木舒克市| 镇原县| 分宜县| 祁连县| 沈丘县| 隆子县| 凌源市| 广水市| 惠来县|