flask

一: flask簡介

  Flask是一個基於Python開發而且依賴jinja2模板和Werkzeug WSGI服務的一個微型框架,對於Werkzeug本質是Socket服務端,其用於接收http請求並對請求進行預處理,而後觸發Flask框架,開發人員基於Flask框架提供的功能對請求進行相應的處理,並返回給用戶,若是要返回給用戶複雜的內容時,須要藉助 jinja2模板來實現對模板的處理,即:將模板和數據進行渲染,將渲染後的字符串返回給用戶瀏覽器。html

二: flask安裝

pip3 install flask

三: flask基本使用

from flask import Flask

app = Flask(__name__)


@app.route('/')
def HelloWorld():
    return "hello world"


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

四: flask的四種響應

from flask import Flask, render_template, redirect, jsonify
# __name__表示所在文件
app = Flask(__name__)


@app.route('/index')
def index():
    # 直接返回字符串
    return "ok"

    # 返回HTML
    info = {'name': "Tom", "age": 19, "gender": "male"}
    dict = {'name': "Tom"}
    return render_template('index.html', name="hello world", info=info, name_dict=dict)

    # 跳轉頁面
    return redirect('/inner')

    # 返回json數據
    name_dict = [{'name': "jason-gdx"}, {'name': "tank-sb"}]
    return jsonify(name_dict)

@app.route('/inner')
def inner():
    return 'hello world'

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

五: flak的配置文件

from flask import Flask

app = Flask(__name__)

# 配置文件
# app.debug = True
# app.secret_key = '123123'

# 以字典的形式
# app.config['DEBUG'] = True

# 以文件的方式
# app.config.from_pyfile('settings.py')

# 以類的形式(推薦使用, 好比: 上線和線下所用的配置文件不同)
app.config.from_object('settings.DevelopmentConfig')


@app.route('/login')
def login():
    print("hello world")
    return 'ok'


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

  各類配置

 {
        'DEBUG':                                get_debug_flag(default=False),  是否開啓Debug模式
        'TESTING':                              False,                          是否開啓測試模式
        'PROPAGATE_EXCEPTIONS':                 None,                          
        'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
        'SECRET_KEY':                           None,
        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
        'USE_X_SENDFILE':                       False,
        'LOGGER_NAME':                          None,
        'LOGGER_HANDLER_POLICY':               'always',
        'SERVER_NAME':                          None,
        'APPLICATION_ROOT':                     None,
        'SESSION_COOKIE_NAME':                  'session',
        'SESSION_COOKIE_DOMAIN':                None,
        'SESSION_COOKIE_PATH':                  None,
        'SESSION_COOKIE_HTTPONLY':              True,
        'SESSION_COOKIE_SECURE':                False,
        'SESSION_REFRESH_EACH_REQUEST':         True,
        'MAX_CONTENT_LENGTH':                   None,
        'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
        'TRAP_BAD_REQUEST_ERRORS':              False,
        'TRAP_HTTP_EXCEPTIONS':                 False,
        'EXPLAIN_TEMPLATE_LOADING':             False,
        'PREFERRED_URL_SCHEME':                 'http',
        'JSON_AS_ASCII':                        True,
        'JSON_SORT_KEYS':                       True,
        'JSONIFY_PRETTYPRINT_REGULAR':          True,
        'JSONIFY_MIMETYPE':                     'application/json',
        'TEMPLATES_AUTO_RELOAD':                None,
    }

六: 路由

  1. 建立路由的兩種方式

from flask import Flask

app = Flask(__name__)

@app.route('/index')
def index():
    pass
# view_func必填
app.add_url_rule('/index', view_func=index)

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

  2. 路由參數

from flask import Flask

app = Flask(__name__)

"""
rule: 路由
methods: 請求方式
endpoint: 起別名, 用於反向解析. url_for('index')
strict_slashes: 設置路由是否爲嚴格模式, True爲嚴格模式, False爲非嚴格模式, 默認爲True
redirect_to: 重定向到指定路徑
"""
@app.route('/index', methods=["GET", "POST"], endpoint='index', strict_slashes=True, redirect_to='/login')
def index():
    return "index"

# app.add_url_rule('/index', view_func=index)
"""
self.add_url_rule(rule, endpoint, f, **potion)參數以下

self: Flask類產生的對象(app)
rule: 路由
endpoint: 取別名, 若是爲空, 用當前的函數名
methods: 請求方式
view_func: 取別名指向的函數(請求該路徑, 要響應的函數)
"""


@app.route('/login')
def login():
    return "login"


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

 

  3. 路由跳轉

from flask import Flask, url_for, redirect

app = Flask(__name__)
app.debug = True

def login():
    return "hello world"

app.add_url_rule('/login', view_func=login, endpoint='login')

def index():
    real_url = url_for('login')
    return redirect(real_url)

app.add_url_rule('/index', view_func=index)

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

 

  4.自定義URL匹配正則表達式

"""
自定義URL匹配正則表達式
    1. 導入from werkzeug.routing import BaseConverter
    2. 先寫一個類, 繼承BaseConverter
        實現: __init__(), to_python(), to_url()方法
    3. app.url_map.converters['regex'] = RegexConverter
    4. 咱們在路由裏面@app.route('/index/<regex("\d+"):nid>'),regex1("正則表達式")
    5. regex("正則表達式")匹配出來的結果,傳給to_python,必定要return
    6. 當咱們作反向解析的解析的時候,咱們的參數,會傳遞給to_url,return的結果纔是咱們拼接到咱們路由上(真正的路由)
"""
from flask import Flask, url_for
from werkzeug.routing import BaseConverter

app = Flask(import_name=__name__)
app.debug = True

class RegexConverter(BaseConverter):

    def __init__(self, map, regex):
        super(RegexConverter, self).__init__(map)
        self.regex = regex

    def to_python(self, value):
        """
        路由匹配時, 匹配成功後傳遞給視圖函數中參數的值
        value: 正則匹配出來的結果
        """
        print(value, type(value),2222222)
        return int(value)

    def to_url(self, value):
        """
        使用url_for反向解析生成URl時, 傳遞的參數通過該方法處理,
        返回的值用於生成URL中的參數
        """
        val = super(RegexConverter, self).to_url(value)
        print(val,3333333)
        return val

# '/index/<regex("\d+"):nid>' ":"後面不能有空格
app.url_map.converters['regex'] = RegexConverter
@app.route('/index/<regex("\d+"):nid>', endpoint="index")
def index(nid):
    print(nid, type(nid),4444444)
    print(url_for('index', nid='999'),55555555)
    # /index/999 55555555
    return "index"

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

  5. 路由(起別名)

from flask import Flask, url_for, redirect, render_template

app = Flask(__name__)
app.debug = True

USERS = {
    1:{'name':'張三','age':18,'gender':'','text':"道路千萬條"},
    2:{'name':'李四','age':28,'gender':'','text':"安全第一條"},
    3:{'name':'王五','age':18,'gender':'','text':"行車不規範"},
}

# @app.route('/detail/<int:nid>',methods=['GET'],endpoint='detail')
def detail(nid):
    print(nid, type(nid))
    return render_template('index.html', info=USERS)

app.add_url_rule('/detail/<int:nid>', view_func=detail)


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

 

  裝飾器

 # 裝飾器函數
 def route(self, rule, **options):

        def decorator(f):
            endpoint = options.pop("endpoint", None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f

        return decorator

# 被裝飾函數
@app.route('/login',methods=['POST', "GET"], endpoint='index')
def login():
    return "hello world"

裝飾器: 先執行裝飾器, 運行裏面的代碼, 返回一個函數名
        而後加括號, 把裝飾器裝飾的函數當成參數傳遞給函數,
        返回一個被裝飾器裝飾的同名函數

七: flask的CBV

from flask import Flask, url_for, views

app =Flask(__name__)
app.debug = True

# class IndexView(views.View):
#     methods = ['GET', "POST"]
#
#     def dispatch_request(self):
#         print('index')
#         return "index"

class IndexView(views.MethodView):

    def get(self):
        return 'index get'

    def post(self):
        return 'index post'

app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))
"""
執行as_view()函數裏面的view函數,
在執行MethodView類中的dispatch_request()函數,
根據請求的方式,進行任務的分發,默認get的請求.

爲何as_view()中藥傳參: 
    若是不傳參, 都是view_func=view, 路由多要報錯
    
至關於endpoint
"""

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

八: .py文件中的標籤渲染頁面的兩種方式

  .py文件

"""
一種: .py文件渲染標籤, 導入Markup
二種: 前端頁面{{ html|safe }}
"""
from flask import Flask, Markup, render_template

app = Flask(__name__)
app.debug = True

def func(st1, st2):
    return Markup(f"<h1>{st1} {st2}!</h1>")

@app.route('/index')
def index():
    html = "<h1>you are beautiful!</h1>"
    return render_template('index.html', func=func, html=html)

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

  html頁面

{{ func('hello', 'world') }}
{{ html|safe}}

九: 請求與響應

from flask import Flask
from flask import request
from flask import make_response
from flask import render_template
from flask import redirect

  1. 請求

    request.args  # get請求提交的數據
    request.form  # post請求提交的數據
    request.values  # post和get提交的數據都在
    request.cookies  # 客戶端攜帶cookie
    request.headers  # 請求頭
    request.path  # 不帶域名, 請求路徑如: /index
    request.full_path  # 不帶域名, 帶參數的請求路徑
    request.script_root
    request.url           帶域名帶參數的請求路徑
    request.base_url      帶域名請求路徑
    request.url_root      域名
    request.host_url      域名
    request.host          127.0.0.1:500
    request.files
    obj = request.files['the_file_name']
    obj.save('/var/www/uploads/' + secure_filename(f.filename))

  2. 響應

    return "字符串"
    return render_template('html模板路徑',**{})
    return redirect('/index.html')
    return jsonify({'k1':'v1'})

    response = make_response(render_template('index.html'))
    response.delete_cookie('key')
    response.set_cookie('key', 'value')
    response.headers['X-Something'] = 'A value'
   return response
    """
    1. 導入make_response
    2. response=make_response(4劍客)
    3. 操做response
    4. return response
    """

十: session和cookie

"""
session和cookie
app.session_interface這裏面看 存session: 1. 調用save_session,將咱們的session加密的val,讀取配置文件['SESSION_COOKIE_NAME']獲得key 2. 將1種的key,val存儲到cookies 取session; 1. 獲取request裏面的cookies,獲取裏面key,這個key就是['SESSION_COOKIE_NAME'],值就是加密的值 2. 對該值進行解密
""" from flask import Flask, session app = Flask(__name__) app.debug = True # 在瀏覽器存儲的key名字 app.config['SESSION_COOKIE_NAME'] = 'session' # 祕鑰 app.secret_key = 'ahsodhfb' # @app.route('/index') def index(): session['hello'] = 'world' return 'ok' # @app.route('/login') def login(): print(session.get('hello')) return 'I am fine' if __name__ == '__main__': app.run()

十一: 閃現

"""
閃現: 可用於記錄日誌

  1. 若是要用flash就必須設置app.secret_key = 'asdfasdf'
  2. 只能取一次,在取就沒有了
  3. 咱們能夠經過 flash('普通訊息',category="info"),對信息作分類
  4. get_flashed_messages(with_categories=True,category_filter=("error",)),with_categories以鍵值對的形式獲取
    咱們設置閃現,category_filter=("error",)進行分類信息的過濾前端

"""
from flask import Flask, flash, get_flashed_messages, jsonify

app = Flask(__name__)
app.debug = True
app.secret_key = 'xhjjjg'

@app.route('/index')
def index():
  # flash(message, category) flash(
"超時錯誤", category="error") flash('普通訊息',category="info") return "ssdsdsdfsd" @app.route('/inner') def inner(): # with_categories=False 表示只顯示信息, 不顯示分類 data = get_flashed_messages(with_categories=False, category_filter=("error", "info")) data1 = get_flashed_messages(with_categories=True, category_filter=("error", "info")) print(data) return "信息有誤" if __name__ == '__main__': app.run()

十二: 中間鍵

from flask import Flask

app = Flask(__name__)
app.debug = True

class MyMiddleware:

    def __init__(self, wsgi_app):
        self.wsgi_app = wsgi_app

    def __call__(self, environ, start_response):
        print('以前作操做')
        res = self.wsgi_app(environ, start_response)
        print('以後作操做')
        return res

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

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

十三: request擴展

  總結: 請求以前有return, 有return的函數執行, 響應函數不執行, 請求以後的函數執行,

     執行的順序和django的中間件同樣, 請求以後的函數必須return response

from flask import Flask, render_template, request

app = Flask(__name__)
app.debug = True

@app.before_request
def before1():
    print(request)
    print('請求1')
    return "111"

@app.before_request
def before2():
    print(request)
    print('請求2')
    return "222"

@app.after_request
def after1(response):
    print("我是請求以後1")
    return response

@app.after_request
def after2(response):
    print("我是請求以後2")
    return response


# 有沒有異常都會執行該函數, 沒有e爲None, 有e爲錯誤信息
@app.teardown_request
def tear(e):
    print(e)

# 捕獲異常, 若是出現異常, 並且狀態是@app.errorhandler(404)
# 能夠作404頁面
@app.errorhandler(404)
def error_404(args):
    print(args)
    return "404錯誤"

# 標籤(前端頁面向後端函數傳數據): template_global
@app.template_global()
def add(a, b):
    return a + b
# {{ add(2, 3) }}

# 過濾器: template_filter
@app.template_filter
def filter(x, y, z):
    return x + y + z
# {{ 2|filter(3, 4) }}

@app.route('/index')
def index():
    print('視圖函數')
    return render_template('index.html')

if __name__ == '__main__':
    app.run()
相關文章
相關標籤/搜索