Flask详细介绍及使用实例

时间:2018-08-27
本文章向大家介绍,需要的朋友可以参考一下

Flask攻略

python三大框架预览

Python Web框架分类
    功能分类:
        a:收发消息相关(socket)
        b:根据不同的URL执行不同的函数(业务逻辑相关的)
        c:实现动态网页(字符串的替换)

    Web框架分类:
        1、自己实现b,c,使用第三方的a(Django)
        2、自己实现b,使用第三方的a,c(Flask)
        3、自己实现abc(Tornado)
两个模块
web服务器程序 《---WSGI协议---》 web应用程序

1、wsgiref
Django开发环境使用的就是wsgiref模块
2、jinja2(Flask)
渲染HTML页面,其实就是实现字符串的替换
python三大框架优缺点

  Flask:

    优点: 小而精,短小精悍,第三方组件特别多

    缺点: 组件更新速度取决于开源者 

  Tornado:

    优点: 原生的WebSocket, 异步任务, IO非阻塞玩

    缺点: 没有组件,Session都没有

  Django:

   优点: 大而全,组件非常全面

    缺点: 太大,重量级框架,加载太大,浪费资源

Flask的优势

Flask中的Werkzuge原理,__call__()
Flask的第一个Hello Flask
Flask的 HTTPresponse render_template redirect
Flask中的 request
Flask中的 Jinja2 ,Markup
Flask中的 session secret_key
Flask中的路由系统 url_for

Flask中Werkzuge原理

from werkzeug.wrappers import Response, Request
from werkzeug.serving import run_simple


# application源码里面 get_wsgi_headers 里面有个__call__方法
# 可以调用__call__ 在执行flk的时候执行call里面的结果
@Request.application
def flk(r):
    print(r.url)
    if r.url == '/123':
        asd()
    return Response("hello")

# flk
run_simple("127.0.0.1", 5500, flk)


def asd():
    print('kermit')


asd()

Flask三剑客

# HTTPresponse: return "Hello Flask"
# render_template: return render_template("login.html") #templates
# redirect: return redirect("/login")

示例:

# Httpresponse
@app.route("/index")
def index():
    return "Hello Flask"


# render_template
@app.route("/login")
def login():
    return render_template("login.html")


# redirect
@app.route("/")
def root_path():
    return redirect("/login")

Flask需要自己开启:(流程如下)

from flask import Flask, render_template, redirect
app = Flask(__name__)
app.run()  # 可以自定义ip 端口  和debug模式

Flask的request

request.method 获取请求方式
request.form 获取FromData数据(通常情况下的POST请求)
request.args    获取GET方式提交的数据
request.files    获取file
request.url_about    获取所有的关于URL的参数
request.values    获取全部提交方式
to_dict    坑,覆盖,GET覆盖POST
request.headers    获取头部信息
request.cookie    获取客户端cookie
request.json    数据头:application/json
request.data    在没有任何数据头的情况提交的POST

Flask的模板语言

# Flask 基于 Jinja2 做了一层小的封装,向前端传递数据 render_template 参数传递 stu = {k1:v1}

{{ stu }}
    <td>{{ stu.name }}</td>
    <td>{{ stu["age"] }}</td>
    {% if stu.get("gender") == ""  %}
        <td>男</td>
    {% else %}
        <td>{{ stu.get("gender") }}</td>
    {% endif %}
    
    
    STUDENT_LIST = [
        {'name': 'stu1', 'age': 38, 'gender': ''},
        {'name': 'stu2', 'age': 73, 'gender': ''},
        {'name': 'stu3', 'age': 84, 'gender': ''}
    ]
    
    <td>{{ stu.0.name }}</td>
    <td>{{ stu[0]["age"] }}</td>
    {% if stu[0].get("gender") == ""  %}
        <td>男</td>
    {% else %}
        <td>{{ stu.0.get("gender") }}</td>
    {% endif %}


    @apl.template_global()
    def a_b_sum(a,b):
        return a+b
    {{ a_b_sum(123,234) }}
    
    @apl.template_filter()
    def a_b_c_sum(a,b,c):
        return a+b+c
    {{ 123 | a_b_c_sum(1,2) }}

注意:安全字符串,Markup相当于模板里面有safe

{{ input | safe }}
    Markup() : Markup("<input type='text' name='input_tag'>")

pycharm识别模板语言的格式:设置jinja2的语言

Session

secret_key = "" 这个是开启session必备的参数

form flask import session
    app.secret_key = "随意"
    session["user"] = "xxxx"
    if session.get("user")

Jsonify

json的转换兼容性比json模块强

from flask import jsonify
# import json
# Flask的jsonify是等同于json
# 区别是json的转换兼容性比json模块强
@flk.route('/json')
def get_json():
    res = {
        "user_id": 1,
        "username": "kermit",
        "password": "123"
    }
    # return json.dumps(res)
    return jsonify(res)

Flask路由

flk.route()

"/index"  路由地址
"/index/<nid>"   动态路由地址(视图函数需要nid参数)
"/index/<int:nid>"   动态路由地址

"/files/<filename>"     <> 里面的filename可以是本地文件内的任何一个文件全名,可以把任意存在的文件内容打印到页面上
# 可以把所有文件内容显示到页面上面
@flk.route('/files/<filename>')
def files(filename):
    return send_file(filename)

补充

methods=["GET","POST"]   允许URL的请求方式
endpoint="index"   反向URL操作,可以解决Inner重名的问题
redirect_to="/index2"   服务器端页面跳转  301永久性重定向
strict_slashes=False   可以使用"/"结尾 反之不可以
defaults={"nid":1}   视图函数默认参数

Flask配置

settings.FlaskSettings

DEBUG = True
app.config["secret_key"] = "xxxxx"
TESTING = True
{
    'DEBUG': False,  # 是否开启Debug模式
    'TESTING': False,  # 是否开启测试模式
    'PROPAGATE_EXCEPTIONS': None,  # 异常传播(是否在控制台打印LOG) 当Debug或者testing开启后,自动为True
    'PRESERVE_CONTEXT_ON_EXCEPTION': None,  # 一两句话说不清楚,一般不用它
    'SECRET_KEY': None,  # 之前遇到过,在启用Session的时候,一定要有它
    'PERMANENT_SESSION_LIFETIME': 31,  # days , Session的生命周期(天)默认31天
    'USE_X_SENDFILE': False,  # 是否弃用 x_sendfile
    'LOGGER_NAME': None,  # 日志记录器的名称
    'LOGGER_HANDLER_POLICY': 'always',
    'SERVER_NAME': None,  # 服务访问域名
    'APPLICATION_ROOT': None,  # 项目的完整路径
    'SESSION_COOKIE_NAME': 'session',  # 在cookies中存放session加密字符串的名字
    'SESSION_COOKIE_DOMAIN': None,  # 在哪个域名下会产生session记录在cookies中
    'SESSION_COOKIE_PATH': None,  # cookies的路径
    'SESSION_COOKIE_HTTPONLY': True,  # 控制 cookie 是否应被设置 httponly 的标志,
    'SESSION_COOKIE_SECURE': False,  # 控制 cookie 是否应被设置安全标志
    'SESSION_REFRESH_EACH_REQUEST': True,  # 这个标志控制永久会话如何刷新
    'MAX_CONTENT_LENGTH': None,  # 如果设置为字节数, Flask 会拒绝内容长度大于此值的请求进入,并返回一个 413 状态码
    'SEND_FILE_MAX_AGE_DEFAULT': 12,  # hours 默认缓存控制的最大期限
    'TRAP_BAD_REQUEST_ERRORS': False,
    # 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样,
    # 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。
    'TRAP_HTTP_EXCEPTIONS': False,
    # Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。
    # 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。
    # 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。
    # 如果这个值被设置为 True ,你只会得到常规的回溯。
    'EXPLAIN_TEMPLATE_LOADING': False,
    'PREFERRED_URL_SCHEME': 'http',  # 生成URL的时候如果没有可用的 URL 模式话将使用这个值
    'JSON_AS_ASCII': True,
    # 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False ,
    # Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。
    # 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。
    'JSON_SORT_KEYS': True,
    #默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。
    # 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。
    # 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。
    'JSONIFY_PRETTYPRINT_REGULAR': True,
    'JSONIFY_MIMETYPE': 'application/json',
    'TEMPLATES_AUTO_RELOAD': None,
}
flask的整套配置项

蓝图(Blueprint)

from flask import Blueprint,render_template,redirect
reg = Blueprint("reg",__name__,template_folder="reg_temp",static_folder="regs",static_url_path="/regs")

@reg.route("/reg")
def reg_user():
  return render_template("reg_index.html")

from flask import Flask
import reg_user
app = Flask(__name__)
app.register_blueprint(reg_user.reg)
if __name__ == '__main__':
  app.run("0.0.0.0", 9527, debug=True)

1.Flask实例配置
app.config.form_object("setting.FlaskSetting")
app.DEBUG = True 开启Debug模式,该完代码不用手动重启
app.SECRET_KEY = "xxxxx" 开启session必备参数


2.初始化配置(Flask,Blueprint)
template_folder="reg_temp",
static_folder="regs",
static_url_path="/regs"

3.蓝图Blueprint
在app实例中注册蓝图app.register_blueprint(reg_user.reg)
实例化蓝图对象reg = Blueprint("reg",__name__,template_folder="reg_temp",static_folder="regs",static_url_path="/regs")
蓝图对象同样与Flask对象,具备独立模板和静态目录

from flask import Blueprint, render_template, redirect
import DATA

student_list = Blueprint('student_list', __name__, static_folder="list_static", static_url_path="/list_static")


# 蓝图实例对象一定不能与视图函数同名
@student_list.route('/list')
def list():
    return render_template('index.html')

4.before_request after_request before_frist_request
before_request 在请求进入视图函数之前做出的处理
after_request 在视图函数返回给用户之前做出的处理
before_frist_request 在第一次请求进入视图函数之前做出的处理

# 类似于Django中间件的功能
@flk.before_request  # 在请求之前
def be1():
    print('在请求进入App之前做出处理')
    # 判断url是不是/login
    if request.path == "/login":
        print('当前访问的页面url是:', request.path)
        # True返回None不作任何操作往下走
        return None
    if session.get("user"):
        print('userSession存在,直接访问页面!')
        return None
    else:
        print('user不存在,跳转到login页面')
        return redirect("/login")


@flk.before_request
def be2():
    print('执行be2')


# 在请求之后
@flk.after_request
def af1(response):
    print('在此时执行了after1')
    return response


@flk.after_request
def af2(response):
    print('在此时执行了after2')
    return response


# 第一次请求前执行
@flk.before_first_request
def be_first():
    print('第一次请求')


# 报错发送的状态码显示的结果
@flk.errorhandler(404)
def error_page(arg):
    return "当前页面不存在!"

5.errorheadler(404)
def error_page(arg)
错误信息头

第一个Flask

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2018/08/27 17:19
# @Author  : MJay_Lee
# @File    : flask_demo_test.py
# @Contact : limengjiejj@hotmail.com


from flask import Flask # 导入Flask类

app = Flask(__name__) # 实例化Flask对象 app

@app.route("/") # app中的route装饰器
def index(): # 视图函数
    return "first flask app"

app.run("0.0.0.0",5000,debug=True) # 启动Flask Web 服务

Werkzuge