【python】Flask

Flask

Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。

django和flask的区别

django是个大而全的框架,flask是一个轻量级的框架。django内部为我们提供了非常多的组件,flask框架本身没有太多的功能但是第三方组件非常齐全。 django的请求处理是逐一封装和传递,flask的请求是利用上下文管理来实现的。

安装

pip3 install flask

Werkzeug

flask依赖wsgi是Werkzeug

from werkzeug.serving import run_simple
from werkzeug.wrappers import BaseResponse
def func(environ, start_response):
	response = BaseResponse("hello")
	return response(environ, start_response)
	
if __name__ == '__main__':
    run_simple('127.0.0.1', 5000, func)

模拟Flask

from werkzeug.serving import run_simple

class Flask(object):
    
    def __call__(self,environ, start_response):
        pass
    
    def run(self):
        run_simple('127.0.0.1', 5000, self)
        
app = Flask()

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

使用Flask

from flask import Flask
# 导入Flask
app = Flask(__name__)
# 创建Flask对象
@app.route("/index")
# 建立路由和函数的对应关系
def index():
    return "index"
if __name__ == "__main__":
    app.run()
    # 启动

路由

路由的两种写法

# 方式一:
@app.route('/index',methods=['GET','POST'],endpoint="login")
# methods指定允许的请求
# endpoint类似django中的别名
def login():
	pass

# 方式二:
def index():
    return render_template('index.html')
app.add_url_rule('/index', 'index', index)
# app.add_url_rule('/路径', '函数名', 函数)

动态路由

@app.route('/index/<int:nid>')
# <int:nid> 接收一个url值,默认为字符串类型,可以通过int:nid这种方式指定类型
def login(nid):
	print(nid)

支持正则表达式的路由

from flask import Flask,render_template

app = Flask(__name__)

from werkzeug.routing import BaseConverter
class RegConverter(BaseConverter):
# 必须继承BaseConverter类
    def __init__(self, map, regex):
        super().__init__(map)
        self.regex = regex
app.url_map.converters['regex'] = RegConverter

@app.route('/index/<regex("\d+"):xx>')
def index(xx):
    return render_template('index.html')

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

视图

FBV

def index():
    return render_template('index.html')
app.add_url_rule('/index', 'index', index)

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

CBV

from flask import Flask,render_template,views
app = Flask(__name__,)

def t1(func):
    def inner(*args,**kwargs):
        result = func(*args,**kwargs)
        return result
    return inner

class Index(views.MethodView):
    methods = ['GET',"POST"]
    # methods :指定允许的请求
    decorators = [t1,]
    # 添加装饰器
    def get(self):
        return 'get'
    def post(self):
        return 'post'

app.add_url_rule('/index', view_func=Index.as_view('user')) 
# app.add_url_rule('url', view_func=类.as_view('endpoint'))

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

获取数据

flask和django一样,都是从request中获取数据,但是flask的request需要导入

from flask import Flask,request

app = Flask(__name__)

@app.route("/index",methods=["GET","POST"])
def index():
    print(request.args)
    print(request.args.get("page"))
    # 获取url中的数据
    print(request.form)
    print(request.form.get("name"))
    # 获取form提交的数据
    return "index"

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

返回值

在flask中不仅可以返回页面、json数据等还可以返回一个函数

返回html文件

html文件默认需要放在templates目录下,如果要指定其他目录可以通过template_folder属性指定

from flask import Flask,request,render_template,redirect,jsonify

app = Flask(__name__,template_folder="htmls")
# template_folder指定存放html的文件夹

@app.route("/index")
def index():
    return render_template("index.html")
    # 返回页面
    return render_template("index.html",name="zxc")
    # 携带值返回页面
    return render_template("index.html",**{name:"zxc"})
    # 值以字典形式返回
    
if __name__ == "__main__":
    app.run()

重定向

需要导入redirect

from flask import Flask,request,render_template,redirect,jsonify,url_for

app = Flask(__name__)

@app.route("/index",methods=["GET","POST"])
def index():
    return redirect("/login")
    # 通过请求路径重定向
    return redirect(url_for("log"))
    # 通过别名重定向
    
if __name__ == "__main__":
    app.run()
    
@app.route("/login",endpoint="log")
def login():
    return "login"

页面使用url_for

{{ url_for('蓝图名.别名' ,参数=值)}}

返回json数据

需要导入jsonify

from flask import Flask,request,render_template,redirect,jsonify

app = Flask(__name__)

@app.route("/index",methods=["GET","POST"])
def index():
    return jsonify([{"name":"1","age":"2"}])

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

模板

flask的模板使用方法和django类似

语法

# 取值
{{ name }}
# 循环
{% for item in obj%}
	{{item}}
	{{item.name}}
	{{item["name"]}}
{% endfor %}
# 使用items时需要手动添加括号
{% for k,v in names.items()%}
{% endfor %}

模板继承

创建模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
	<h1>1</h1>
    {% block content %} 
    
    {% endblock %}
</body>
</html>

导入模板

{% extends 'base.html' %}
{% block content %}
    <h1>2</h1>
{% endblock %}

组件

将一个页面作为组件加载到另一个页面中

{% include '2.html' %}

全局模板

定义在蓝图中时只能在本蓝图中使用

from flask import Flask,render_template,views
app = Flask(__name__,)

@app.template_global()
# 类似django中的自定义标签
def func(arg):
	# arg:接受参数
    return 'str1' + arg
    
@app.template_filter() 
# 类似django中的自定义筛选器
def x1(s1,s2):
    return 'str3' + s1 + s2

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

if __name__ == '__main__':
    app.run()
<body>
{{ func("str2") }}
{{ "str4"|func2("str5") }}
</body>

静态文件

flask中默认静态文件要放在static目录中,可以通过static_folder指定存放静态文件的目录

from flask import Flask,render_template
app = Flask(__name__,static_folder="statics",static_url_path="/pac")
# static_folderL:指定存放静态文件的目录
# static_url_path:指定页面上静态文件的“路径“,默认为static

@app.route("/index")
def index():
   return render_template("index.html")
<body>
<!--方式一:固定写法,static_url_path改变路径不会变-->
<img src="/pic/1.jpg" />
<!--/pic=static_url_path设定的值-->

<!--方式二:动态写法,随着static_url_path改变-->
<img src="{{ url_for('static',filename='1.jpg' )}}" />

<!--包含子路径的写法-->
<script src="{{ url_for('static',filename='js/bootstrap.min.js' )}}"></script>
</body>

配置文件

全局变量实现:

# /config/settings.py
NAME = "XZC"

try:
    from .localsettings import *
    # 导入另一个文件中的全部配置
except ImportError:
    pass
from flask import Flask
app = Flask(__name__)
app.config.from_object("config.settings")
# 加载配置
@app.route("/index")
def index():
    print(app.config["NAME"])
    # 读取配置文件
    return "hello"

基于类实现:

# /config/settings.py
class BaseSettings:
    """公共配置"""

class DevSettings(BaseSettings):
    """私有配置"""
    NAME = "zxc"
from flask import Flask
app = Flask(__name__)
app.config.from_object("config.settings.DevSettings")
# 导入settings
@app.route("/index")
def index():
    print(app.config["NAME"])
    return "hello"

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

session

django中的session和flask中的session有一些不同,django中的session是存放在服务器上的,而flask的session是存放在浏览器上的。使用session需要设置secret_key 值随意,服务器会对session数据和secret_key 进行加密,然后将加密后的字符串返回给浏览器,保存在浏览器的cookie中。当浏览器携带这个密文访问时,flask会自动将密文进行解密。

from flask import Flask,request,session

app = Flask(__name__,template_folder="a")

app.secret_key = "dhuaicnjk"
# 设置secret_key 
@app.route("/index",methods=["GET","POST"])
def index():
    if request.method == "GET":
        session["name"] = "zxc"
        # 设置session
        return "index"
    name = session.get("name")
    # 取出session
    return name

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

装饰器

flask使用装饰器时要放在@app.route()下,装饰器中必须使用functools

from flask import Flask,request,session,render_template
import functools

app = Flask(__name__)
app.secret_key = "dhuaicnjk"

def auth(func):
    # 需要使用functools保证被装饰的函数的名称不变
    @functools.wraps(func)
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner

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

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

蓝图

flask中的蓝图类似于django的app,和djasngo的app不同的是,django中需要在配置文件中注册app,而flask的蓝图是通过导入来使用

创建蓝图:

#views.bp1.py
from flask import Blueprint
# 导入Blueprint
bp1 = Blueprint('bp1',__name__)
# 创建蓝图
@bp1.route('/index')
def index():
    return 'index'

导入蓝图:

from flask import Flask
from views.bp1 import bp1
# 导入蓝图
app = Flask(__name__)
app.register_blueprint(bp1)
# 使用蓝图
# app.register_blueprint(bp1,url_prefix='/web')
# url_prefix类似django的路由分发
if __name__ == '__main__':
    app.run()

基于蓝图的两种项目目录形式

方式一

在这里插入图片描述

# manage.py
from flask1 import create_app
app = create_app()
if __name__ == '__main__':
    app.run()
# __init__.py
from flask import Flask
from .views.login import log

def create_app():
    app = Flask(__name__)
    app.secret_key = 'asdfaskdfjsd'
    @app.route('/index')
    def index():
        return 'index'
    app.register_blueprint(log)
    return app
# login.py
from flask import Blueprint
log = Blueprint('log',__name__)
@log.route('/login')
def login():
    return 'login'

方式二

在这里插入图片描述

# manage.py
from flask1 import create_app
app = create_app()
if __name__ == '__main__':
    app.run()
# /flask/__init__.py
from flask import Flask
def create_app():
    app = Flask(__name__)
    app.config.from_object('config.settings')
    from .index import index
    app.register_blueprint(index)
    return app
# /flask/index/__init__.py
from flask import Blueprint
index = Blueprint('index',__name__)
# /flask/index/views/index.py
from .. import index
from flask import render_template

@index.route('/login')
def login():
    return render_template('index.html')

特殊装饰器

类似与django中的中间件,定义在蓝图中时,只作用于本蓝图

from flask import Flask,render_template,request

app = Flask(__name__)

@app.before_request
def f1():
	# 不返回或返回空执行下一个before_request
	# 如果返回了东西,那么返回了什么页面就会展示什么,并不再继续执行

@app.after_request
def f2(response):
	# response参数必须有
    return response

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

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

g

在一次请求请求的周期,可以在g中设置值,在本次的请求周期中都可以读取或复制。
相当于是一次请求周期的全局变量。

from flask import Flask,g

app = Flask(__name__)

@app.before_request
def f1():
	g.x1 = 123
@app.route('/index')

def index():
	print(g.x1)
	return 'hello world'
	
if __name__ == '__main__':
	app.run()

信号

信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作。

安装:

pip install blinker

使用

1.中间件

from flask import Flask,render_template

app = Flask(__name__)

@app.route("/index")
def index():
    return "index"
class MyMiddleware():
    def __init__(self,old_app):
        self.wsgi_app = old_app.wsgi_app
    def __call__(self, *args, **kwargs):
        # 在此进行操作
        return self.wsgi_app(*args, **kwargs)

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

2appcontext_pushed

当app_ctx被push到local中栈之后,会触发appcontext_pushed信号,之前注册在这个信号中的
方法,就会被执行。

from flask import Flask,render_template
from flask import signals

app = Flask(__name__)
@ signals.appcontext_pushed.connect
def func(arg):
    print("appcontext_pushed被触发",arg)
    
@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

3.before_first_request

from flask import Flask,render_template
app = Flask(__name__)
@app.before_first_request
def func():
    print("before_first_request被触发")
@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

4.request_started

from flask import Flask,render_template
from flask import signals
app = Flask(__name__)
@signals.request_started.connect
def func(arg):
    print("request_started被触发",arg)

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

5.url_value_processor

from flask import Flask,render_template
app = Flask(__name__)
@app.url_value_preprocessor
def func(endpoint,view_args):
    print("url_value_preprocessors被触发")

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

6.before_reuqest

from flask import Flask,render_template
app = Flask(__name__)
@app.before_request
def func():
    print("before_request被触发")

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

视图函数

7.before_render_templatetemplate_rendered

from flask import Flask,render_template
from flask import signals
app = Flask(__name__)
@signals.before_render_template.connect
def func(app, template, context):
    print("before_render_template被触发")

@signals.template_rendered.connect
def func2(app, template, context):
    print("template_rendered被触发")

@app.route("/index")
def index():
    return render_template("index.html")
if __name__ == '__main__':
    app.run()

8.after_request

from flask import Flask,render_template
app = Flask(__name__)
@app.after_request
def func(response):
    print("after_request被触发")
    return response

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

9.request_finished

from flask import Flask,render_template
from flask import signals
app = Flask(__name__)
@signals.request_finished.connect
def func(app,response):
    print("request_finished被触发")

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

10.got_request_exception

报错执行

from flask import Flask,render_template
from flask import signals
app = Flask(__name__)
@signals.got_request_exception.connect
def func(app,exception):
    print("got_request_exception被触发")

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

11.teardown_request

from flask import Flask,render_template
app = Flask(__name__)
@app.teardown_request
def func(exc):
    print("do_teardown_request  被触发")

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

12.request_tearing_down

from flask import Flask,render_template
from flask import signals
app = Flask(__name__)
@signals.request_tearing_down.connect
def func(app,exc):
    print("request_tearing_down  被触发")

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

13.appcontext_popped

from flask import Flask,render_template
from flask import signals
app = Flask(__name__)
@signals.appcontext_popped.connect
def func(app):
    print("appcontext_popped  被触发")

@app.route("/index")
def index():
    return "index"
if __name__ == '__main__':
    app.run()

Flask源码

在这里插入图片描述

示例链接

流程

准备阶段:

  1. 实例化Flask对象
  2. 加载配置文件(给app的config进行赋值)
  3. 添加路由映射
  4. 运行flask,当有用户请求,执行app.__call__方法。

请求到来:

  1. 创建ctx = RequestContext对象,其内部封装了 Request对象和session数据。
  2. 创建app_ctx = AppContext对象,其内部封装了App和g。
  3. 执行ctx.push触发将 ctx 和 app_ctx 分别通过自己的LocalStack对象将其放入到Local中,Local的
    本质是以线程ID为key,以{“stack”:[]}为value的字典
  4. 执行所有的before_request函数
  5. 执行视图函数
  6. 执行所有after_request函数(session加密放到cookie中)
  7. 销毁ctx和app_ctx

flask-script

flask的组件,用于运行flask程序。

安装

pip3 install flask-script
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值