flask 配置文件 路由 视图 模板 中间件

Posted saoqiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flask 配置文件 路由 视图 模板 中间件相关的知识,希望对你有一定的参考价值。

今日概要

  • wsgi
  • 创建flask对象
    • 模板
    • 静态文件
  • 路由系统
    • 路由的应用:装饰器(推荐)、方法
    • 动态路由
  • 视图
    • FBV
    • CBV
  • 模板
    • 继承
    • include
    • 自定义标签
  • 特殊装饰器
    • before_request充当中间件角色

wsgi 找源码的流程

不依赖与flask

from werkzeug.serving import run_simple
from werkzeug.wrappers import BaseResponse

def func(environ, start_response):
    print('请求来了')
    response = BaseResponse('你好')
    return response(environ, start_response)


if __name__ == '__main__':
    run_simple('127.0.0.1', 5000, func)
"""
    1.程序启动,等待用户请求到来
        app.run()
    2.用户请求到来 app()    
        app.__call__
"""

from flask import Flask

app = Flask(__name__)

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

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

flask对象静态文件的处理

静态文件的处理。

技术图片

view

from flask import Flask,render_template

app = Flask(__name__,template_folder='templates',static_folder='static',static_url_path='/xx')

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

if __name__ == '__main__':
    app.run()
    
#static_folder参数代表静态文件夹名字
#static_folder参数 相当与别名 用这个别名就可以找到文件夹
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>首页</h1>
<!--    <img src="/xx/mm.jpg" />-->

    <!-- 建议 -->
    <img src="{{ url_for('static',filename='mm.jpg')}}" />
</body>
</html>

#static会自动帮你找 不管你是什么 xx还是什么

配置文件

创建一个config文件夹 里面有 配置文件全局setting.py与局部localsettings.py配置文件

py文件导入

配置文件尽量大写

# app.py<br>from flask import Flask
 
app = Flask(__name__)
 
app.config.from_pyfile("settings.py")  # 加载配置文件setting 
 
print(app.config['XX'])#打印配置文件中的XX变量

@app.route("/")
def index():
    return "hello"
 
 
if __name__ == '__main__':
    app.run()
 
 
# settings.py
 
DEBUG = True
...  

setting.py

#方便测试
try:
    from .localsettings import *
except ImportError:
    pass

localsettings.py

用于自己测试

XX=11

基于类的方式 路径方式导入

技术图片

app.py

from flask import Flask
 
app = Flask(__name__)
 
app.config.from_object("test.settings.TestingConfig")    # 系统环境需能找到的模块路径,默认在app同级目录下
app.config.from_object("test.settings.Config") #加载
 
@app.route("/")
def index():
    return "hello"
 
 
if __name__ == '__main__':
    app.run()

settings.py

class Config(object):#公共配置
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite://:memory:'
 
 
class ProductionConfig(Config):#其他配置
    DATABASE_URI = 'mysql://user@localhost/foo'
 
 
class DevelopmentConfig(Config):
    DEBUG = True
 
 
class TestingConfig(Config):#配置类
    TESTING = True  

路由系统

  • 路由的两种写法

    def index():
        return render_template('index.html')
    app.add_url_rule('/index', 'index', index)
    
    
    # 公司里一般用这种方式
    @app.route('/login')
    def login():
        return render_template('login.html')
    
  • 路由加载的源码流程

    - 将url和函数打包成为 rule 对象
    - 将rule对象添加到map对象中。
    - app.url_map = map对象
    
  • 动态路由

    @app.route('/login')
    def login():
        return render_template('login.html')
    
    @app.route('/login/<name>')
    def login(name):
      print(type(name))
        return render_template('login.html')
    
    @app.route('/login/<int:name>')
    def login(name):
      print(type(name))#int类型
        return render_template('login.html')
    
  • 支持正则表达式的路由

    from flask import Flask,render_template
    
    app = Flask(__name__)
    
    #-----------------
    固定写法
    from werkzeug.routing import BaseConverter
    class RegConverter(BaseConverter):
        def __init__(self, map, regex):
            super().__init__(map)
            self.regex = regex
    app.url_map.converters['regex'] = RegConverter
    #--------------------
    
    @app.route('/index/<regex("d+"):x1>')
    def index(x1):
        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 test1(func):
    def inner(*args,**kwargs):
        print('before1')
        result = func(*args,**kwargs)
        print('after1')
        return result
    return inner

def test2(func):
    def inner(*args,**kwargs):
        print('before2')
        result = func(*args,**kwargs)
        print('after2')
        return result
    return inner


class UserView(views.MethodView):
    methods = ['GET',"POST"]#设置可以通过的请求

    decorators = [test1,test2]#设置可以通过的方法


    def get(self):
        print('get')
        return 'get'

    def post(self):
        print('post')
        return 'post'

app.add_url_rule('/user',view_func=UserView.as_view('user')) # endpoint

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

模板

基本用法

flask比django更加接近Python。

from flask import Flask,render_template

app = Flask(__name__,)

def func(arg):
    return '你好' + arg

@app.route('/md')
def index():
    nums = [11,222,33]
    return render_template('md.html',nums=nums,f=func)


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

模板

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

组件

<form action="">
    <input type="text">
    <input type="text">
    <input type="text">
    <input type="text">
    <input type="text">
</form>

继承模板 使用组件 使用函数

{% extends 'layout.html' %}


{% block content %}
    <h1>MD</h1>
    {% include 'form.html' %}
    {{ f("汪洋") }}
{% endblock %}

定义全局模板方法

from flask import Flask,render_template

app = Flask(__name__,)

#在哪个模板都可以用
@app.template_global() # 使用方法1 {{ func("赵海宇") }}
def func(arg):
    return '海狗子' + arg

@app.template_filter() #使用方法2 {{ "赵海宇"|x1("孙宇") }}
def x1(arg,name):
    return '海狗子' + arg + name


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

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

注意:在蓝图中注册时候,应范围只有本蓝图。

特殊装饰器 类似中间件

类似中间件

from flask import Flask,render_template,request

app = Flask(__name__)

@app.before_request#视图函数前执行
def f1():
    if request.path == '/login':
        return
    print('f1')
    # return '123'#有返回值就不会往下执行了

@app.after_request#视图函数后执行
def f10(response):
    print('f10')
    return response

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

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

多个装饰器

from flask import Flask,render_template,request

app = Flask(__name__)

@app.before_request
def f1():
    print('f1')

@app.before_request
def f2():
    print('f2')

@app.after_request
def f10(response):
    print('f10')
    return response

@app.after_request
def f20(response):
    print('f20')
    return response

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

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

注意:before_after request可以在蓝图中定义,在蓝图中定义的话,作用域只在本蓝图。

小细节

from flask import Flask,render_template

app = Flask(__name__,)

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


@app.before_request
def func():
    print('xxx')

#另一种写法
def x1():
    print('xxx')
app.before_request(x1)

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

赠送:threading.local

https://www.cnblogs.com/aaronthon/p/9457330.html

假如,开了十个线程并且做同样的一件事,他们需要带着自己的数据进来,完成事情后带着自己的数据出去。如果是并发,同时进来,他们的数据就会混乱。

一般情况,我们加锁就可以了,一个人先进来,先加锁,另一个人过来看到加锁了,就在外面等,等里面的人出来,自己进去加锁,这样就不会出现数据混乱的问题。

另一种解决方法就是threading.local()来解决问题。

import time
import threading

# 当每个线程在执行 val1.xx=1 ,在内部会为此线程开辟一个空间,来存储 xx=1
# val1.xx,找到此线程自己的内存地址去取自己存储 xx
val1 = threading.local()

def task(i):
    val1.num = i
    time.sleep(1)
    print(val1.num)

for i in range(4):
    t = threading.Thread(target=task,args=(i,))
    t.start()

以上是关于flask 配置文件 路由 视图 模板 中间件的主要内容,如果未能解决你的问题,请参考以下文章

Flask框架 之 功能详解

Flask 简单使用

flask如何设置模板语言Jinjia?如何查看路由视图函数映射?

1.flask基础

python-flask复习—— 装饰器的坑及解决办法flask中的路由/实例化配置/对象配置/蓝图/特殊装饰器(中间件重定义错误页面)

python高级之Flask框架