flask - 进阶

flask 进阶

上下文管理和SQLHelper

```python
import pymysql
from DBUtils.PooledDB import PooledDB

class SqlHelper(object):
    def __init__(self):
        self.pool = PooledDB(
            creator=pymysql,  # 使用链接数据库的模块
            maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
            mincached=2,  # 初始化时,链接池中至少创建的链接,0表示不创建
            blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
            ping=0,
            # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
            host='127.0.0.1',
            port=3306,
            user='root',
            password='222',
            database='cmdb',
            charset='utf8'
        )

    def open(self):
        conn = self.pool.connection()
        cursor = conn.cursor()
        return conn,cursor

    def close(self,cursor,conn):
        cursor.close()
        conn.close()

    def fetchall(self,sql, *args):
        """ 获取所有数据 """
        conn,cursor = self.open()
        cursor.execute(sql, args)
        result = cursor.fetchall()
        self.close(conn,cursor)
        return result

    def fetchone(self,sql, *args):
        """ 获取所有数据 """
        conn, cursor = self.open()
        cursor.execute(sql, args)
        result = cursor.fetchone()
        self.close(conn, cursor)
        return result

    def __enter__(self):
        return self.open()[1]

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(exc_type, exc_val, exc_tb)


db = SqlHelper()
```

概要

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

详细

1.wsgi 找源码的流程

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()

2.flask对象

静态文件的处理。

推荐

from flask import Flask,render_template

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

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

if __name__ == '__main__':
    app.run()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>首页</h1>
    <img src="/static/xx/xx/mm.jpg" />
    
    <!-- 建议 -->
    <img src="{{ url_for('static',filename='xx/xx/mm.jpg')}}" />
</body>
</html>

3.配置文件

3.1 基于全局变量

3.2 基于类的方式

4.路由系统

  • 路由的两种写法

    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))
        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()
    

5.视图

5.1 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')

5.2 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()

6.模板

6.1 基本用法

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 %}

6.2 定义全局模板方法

from flask import Flask,render_template

app = Flask(__name__,)

@app.template_global() #  {{ func("赵海宇") }}
def func(arg):
    return '海狗子' + arg

@app.template_filter() # {{ "赵海宇"|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()

注意:在蓝图中注册时候,应用返回只有本蓝图。

7.特殊装饰器

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可以在蓝图中定义,在蓝图中定义的话,作用域只在本蓝图。

8.小细节

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

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()
posted @ 2020-08-06 17:43  赵刚、  阅读(138)  评论(0编辑  收藏  举报