Flask初见(一)

第一步创建虚拟环境

1、安装虚拟环境模块
pip3 install virtualenv

2、切换指定目录

C:\Users\Administrator>cd /d H:

3、创建虚拟环境

virtualenv 虚拟环境名称

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

第二步安装Flask

pip3 install flask

一、基本使用

from flask import Flask
# 实例化flask对象
app = Flask(__name__)
# 将'/'和hello_world函数绑定到路由中
'''
{
    '/':hello_world
}
'''


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    # 监听用户请求
    # 如果有用户请求,则执行app得__call__方法
    app.run()

一个登陆的简单应用

"""
简单实例
"""

from flask import Flask,render_template,request,redirect,session,url_for
app = Flask(__name__)
app.debug = True  # 开启调试模式
app.secret_key='password_key' # 使用session必须设置secret_key密钥
'''
templates:默认模板文件夹名称
render_template:渲染页面方法
request:请求
redirect:跳转页面
session:session操作
url_for:url别名
'''


def auth(func):
    def inner(*args, **kwargs):
        user = session.get('user_info')
        if not user:
            return redirect('/login')
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result
    return inner


@app.route('/login',methods=['GET','POST'])
def login():
    if request.method=='GET':

        return render_template('login.html')
    else:
        # query_string--url里所有得数据
        # request.query_string
        # form--请求体里的数据
        user = request.form.get('user')
        pwd = request.form.get('pwd')

        if user=='admin' and pwd=='123456':
            session['user_info'] = user
            # 使用url_for反向生成/index
            url = url_for('index')
            return redirect(url)
        else:
            return render_template('login.html',error='用户名或密码错误!')


USERS = {
    1:{'name':'小明','age':'18','gender':'','text':'我是一个大暖男1'},
    2:{'name':'小黑','age':'19','gender':'','text':'我是一个大美女2'},
    3:{'name':'小白','age':'28','gender':'','text':'我是一个大暖男3'},
}


@app.route('/index',methods=['GET'],endpoint='index')
@auth
def index():
    '''
    methods:请求方法
    endpoint:别名
    :return:
    '''
    return render_template('index.html',user_dict = USERS)


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

if __name__ == '__main__':
    app.run()
demo.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户登陆</h1>
    <form method="post">
        <input type="text" name="user">
        <input type="password" name="pwd">

        <input type="submit" value="登陆"> {{ error }}
    </form>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
    <!--注意模板语音字典需要items(),否则不可迭代-->
        {% for k,v in user_dict.items() %}
            <tr>
                <td>{{ k }}</td>
                <!--通过三种当时获取字典数据-->
                <td>{{ v.name }} {{ v['name'] }} {{ v.get('name') }}</td>
                <td><a href="/detail/{{ k }}">查看详细</a></td>
            </tr>
        {% endfor %}
    </table>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>详细信息</h1>
    <div>
        {{ info.name }}
        {{ info.text }}
    </div>
</body>
</html>
detail.html

二、配置文件

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为: 
{
        '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,
    }

# 方式一
app.debug = True
# 方式二
app.config['DEBUG'] = True
app.config.from_pyfile("python文件名称")
        如:
            settings.py
                DEBUG = True
            app.config.from_pyfile("settings.py")
 
    app.config.from_envvar("环境变量名称")
        环境变量的值为python文件名称名称,内部调用from_pyfile方法
 
 
    app.config.from_json("json文件名称")
        JSON文件名称,必须是json格式,因为内部会执行json.loads
 
    app.config.from_mapping({'DEBUG':True})
        字典格式
 
    app.config.from_object("python类或类的路径")
 
        app.config.from_object('pro_flask.settings.TestingConfig')
 
        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
 
        PS: 从sys.path中已经存在路径开始写
     
 
    PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录
配置文件
"""
配置文件
"""

from flask import Flask
app = Flask(__name__)
# 常用方式
app.config.from_object("settings.DevelopmentConfig")


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.run()
配置文件推荐方式 app.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
配置文件推荐方式 settings.py

三、路由系统

@app.route('/user/<username>') # <任意参数>
@app.route('/post/<int:post_id>') # <int:整数型>
@app.route('/post/<float:post_id>') # <float:浮点型>
@app.route('/post/<path:path>') # <path:路径>
@app.route('/login', methods=['GET', 'POST']) # methods=请求方式

对应处理关系

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,  # 匹配any中存在的地址
    'path':             PathConverter,  # 匹配路径
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,  # 匹配 UUID(x-x-x-xxx-xxxx)之类的字符串
}
"""
路由系统
"""

from flask import Flask
app = Flask(__name__)
app.secret_key = "abc123"
# 先执行
'''
    第一步:
    def route(self, rule, **options):
        # rule ----> '/'
        # **options ----> methods=['GET','POST'],endpoint='index'
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator
        
    第二步:
    @decorator----> decorator(index)
    执行----> self.add_url_rule(rule, endpoint, f, **options)
        self:app对象
        rule:url
        endpoint:url别名
        f:执行函数
        **options:其他参数
    最终执行----> app.add_url_rule('/', 'index', index, methods=['GET','POST'])
    
'''


@app.route('/',methods=['GET','POST'],endpoint='index')
def index():
    return '@app.route的路由'


def index2():
    return 'app.add_url_rule的路由'
app.add_url_rule('/index','index2',index2,methods=['GET','POST'])


if __name__ == '__main__':
    app.run()
路由原理
"""
路由系统 CBV形式
"""

from flask import Flask,views

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

# 装饰器
def auth(func):
    def inner(*args, **kwargs):
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result
    return inner

# 方式一 需要自己做分发
class IndexView(views.View):
    methods = ['GET']
    decorators = [auth, ]

    def dispatch_request(self):
        print('Index')
        return 'Index!'


app.add_url_rule('/index1', view_func=IndexView.as_view(name='index1'))  # name=endpoint

# 方式二 推荐使用
class IndexView(views.MethodView):
    methods = ['GET','POST']  # 定义方法
    decorators = [auth, ]  # 装饰器放置位置

    def get(self):
        return 'Index.GET'

    def post(self):
        return 'Index.POST'


app.add_url_rule('/index2', view_func=IndexView.as_view(name='index2'))  # name=endpoint

if __name__ == '__main__':
    app.run()
路由系统 CBV形式
"""
app.route和app.add_url_rule参数
"""

from flask import Flask

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

"""
@app.route和app.add_url_rule参数:
rule,                       URL规则
view_func,                  视图函数名称
defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
methods=None,               允许的请求方式,如:["GET","POST"]
strict_slashes=None,        对URL最后的 / 符号是否严格要求,【False不严格匹配,True严格匹配,默认严格匹配】
redirect_to=None,           重定向到指定地址
subdomain=None,             子域名访问
"""


@app.route('/demo1', methods=['GET', 'POST'], endpoint='demo1',defaults={'nid':888})
def demo1(nid):
    print(nid)
    return 'defaults 举例'


@app.route('/demo2', methods=['GET', 'POST'], endpoint='demo2',strict_slashes=False)
def demo2():
    return 'strict_slashes 举例'


@app.route('/demo3', methods=['GET', 'POST'], endpoint='demo3',redirect_to='/demo2')
def demo2():
    return 'redirect_to 举例'

if __name__ == '__main__':
    app.run()
app.route和app.add_url_rule参数
from flask import Flask
app = Flask(import_name=__name__)
app.config['SERVER_NAME'] = 'mysite.com'  # 域名配置
"""
C:\Windows\System32\drivers\etc\hosts 文件添加本地域名解析映射关系
127.0.0.1  www.mysite.com
127.0.0.1  admin.mysite.com
"""


@app.route("/", subdomain="admin")  # 访问地址 http://admin.mysite.com/
def static_index():
    """Flask supports static subdomains
    This is available at static.your-domain.tld"""
    return "admin.mysite.com"


@app.route("/dynamic", subdomain="<sitename>")  # 访问地址 http://动态地址.mysite.com/
def dynamic_index(sitename):
    """Dynamic subdomains are also supported
    Try going to user1.your-domain.tld/dynamic"""
    return sitename + ".mysite.com"


if __name__ == '__main__':
    app.run(host='127.0.0.1',port=80)
subdomain举例
"""
自定义URL匹配正则表达式
"""

from flask import Flask, url_for
from werkzeug.routing import BaseConverter
app = Flask(import_name=__name__)


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

    def to_python(self, value):
        """
        路由匹配时,匹配成功后传递给视图函数中参数的值
        :param value:
        :return:
        """
        return value

    def to_url(self, value):
        """
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
        :param value:
        :return:
        """
        val = super(RegexConverter, self).to_url(value)
        return val

# 添加到flask中
app.url_map.converters['regex'] = RegexConverter


@app.route('/<regex("demo\d+"):nid>')
def index(nid):
    print(nid) # demo2
    print(url_for('index', nid='demo888'))  # /demo888
    return 'Index'


if __name__ == '__main__':
    app.run()
自定义URL匹配正则表达式

四、模板使用

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


def fun1(arg):
    return " <input type='text' name='' value='' placeholder='%s' >" %arg


def fun2(arg):
    return Markup(" <input type='text' name='' value='' placeholder='%s'>" %arg)

@app.route('/')
def index():
    return render_template(
        'index.html',
        f1=fun1,
        f2=fun2
    )


if __name__ == '__main__':
    app.run()
自定义模板使用py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>
        {{ f1("前端safe") | safe }}
        {{ f2("后端Markup") }}
    </div>

    <div>
        {% macro f3(name,placeholder,type='text', value='') %}
        <input type="{{ type }}" name="{{ name }}1" value="{{ value }}" placeholder="{{ placeholder }}1">
        <input type="{{ type }}" name="{{ name }}2" value="{{ value }}" placeholder="{{ placeholder }}2">
        <input type="{{ type }}" name="{{ name }}3" value="{{ value }}" placeholder="{{ placeholder }}3">
        <input type="{{ type }}" name="{{ name }}4" value="{{ value }}" placeholder="{{ placeholder }}4">
        <input type="{{ type }}" name="{{ name }}5" value="{{ value }}" placeholder="{{ placeholder }}5">
        {% endmacro %}

        {{ f3('n1','宏定义') }}
    </div>
</body>
</html>
自定义模板使用html

注意:Markup等价django的mark_safe

五、请求响应相关

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

app = Flask(__name__)


@app.route('/', methods=['GET', "POST"])
def index():
    # 请求相关信息
    # request.method
    # request.args   # url?a=888
    # request.form   # form 请求体里的数据
    # request.query_string  # url里所有得数据
    # request.values
    # request.cookies
    # request.headers
    # request.path
    # request.full_path
    # request.script_root
    # request.url
    # request.base_url
    # request.url_root
    # request.host_url
    # request.host
    # request.files
    
    # obj = request.files['the_file_name']  # 文件
    # obj.save('/var/www/uploads/' + secure_filename(obj.filename))  # secure_filename重命名

    # 响应相关信息
    # return "字符串"
    # return render_template('html模板路径',**{})
    # return redirect('/index')
    # return jsonify({'k':'v'})

    # make_response回写cookie和响应头
    # response = make_response(render_template('index'))  
    # response是flask.wrappers.Response类型
    # response.delete_cookie('key')
    # response.set_cookie('key', 'value')
    # response.headers['X-Something'] = 'A value'
    # return response

    return "请求和响应"


if __name__ == '__main__':
    app.run()
请求体&响应体

六、Session&Cookie

flask内置session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。

-- 设置:session['username'] = 'xxx'

-- 删除:session.pop('username', None)

"""
session
"""
from flask import Flask,session
app = Flask(__name__)
app.secret_key='加密字符串'


@app.route('/')
def index():
    # flask 内置的session使用 通过app.secret_key加密字符串来保存session和cookie
    session['k1']='v1'
    session['k2']='v2'
    return 'Hello World!'


if __name__ == '__main__':
    app.run()
Flask内置session使用

七、蓝图

蓝图用于目录结构划分 

单个app:示例

多个app:示例

蓝图URL前缀:xxx = Blueprint('account', __name__,url_prefix='/xxx',template_folder='tpl_blogs')    统一指定某一类蓝图下加url前缀url_prefix;template_folder可以设置单独蓝图模板路径

蓝图子域名:xxx = Blueprint('account', __name__,subdomain='admin')
# 前提需要给配置SERVER_NAME: app.config['SERVER_NAME'] = 'mysite.com:5000'
# 访问时:admin.mysite.com:5000/login

八、闪现

基于session实现的闪现需要导入模块flash--设置值,get_flashed_messages--获取值

应用场景:返回错误信息

from flask import Flask,flash,get_flashed_messages,jsonify

app = Flask(__name__)
app.secret_key = 'password_key'


@app.route('/get')
def get():
    # 从某个地方获取设置过得所有值,并清除
    data = get_flashed_messages()
    return jsonify(data)


@app.route('/set')
def sets():
    # 向某个地方设置一个值
    flash('向某个地方设置一个值')
    return 'index'


if __name__ == '__main__':
    app.run()
闪现
from flask import Flask,flash,get_flashed_messages,request,redirect
"""
闪现是对临时数据的操作,基于session 
"""
app = Flask(__name__)
app.secret_key = 'password_key'


@app.route('/index')
def index():
    val = request.args.get('v')
    if val == 'old':
        return 'hello word'
    flash('超时错误',category="s1") # category 分类
    return redirect('/error')


@app.route('/error')
def error():
    """
    展示错误信息
    :return:
    """
    data = get_flashed_messages() # data = get_flashed_messages(category_filter='s1') 只拿这一类数据
    if data:
        msg = data[0]
    else:
        msg = '....'
    return "错误信息:——%s"%(msg,)

if __name__ == '__main__':
    app.run(port=80)
基本使用

九、请求拓展(中间件)

from flask import Flask,render_template,request,redirect,session,url_for
app = Flask(__name__)
app.debug = True  # 开启调试模式
app.secret_key='password_key' # 使用session必须设置secret_key密钥
USERS = {
    1:{'name':'小明','age':'18','gender':'','text':'我是一个大暖男1'},
    2:{'name':'小黑','age':'19','gender':'','text':'我是一个大美女2'},
    3:{'name':'小白','age':'28','gender':'','text':'我是一个大暖男3'},
}


@app.before_request  # 请求之前
def process_request(*args,**kwargs):
    print('请求之前--基于中间件做的登陆')
    # 设置白名单
    White_list = ['/login','/admin',]
    if request.path in White_list:
        return None

    user = session.get('user_info')
    if user:
        return None

    return redirect('/login')

@app.route('/login',methods=['GET','POST'])
def login():
    if request.method=='GET':

        return render_template('login.html')
    else:
        # query_string--url里所有得数据
        # request.query_string
        # form--请求体里的数据
        user = request.form.get('user')
        pwd = request.form.get('pwd')

        if user=='admin' and pwd=='123456':
            session['user_info'] = user
            # 使用url_for反向生成/index
            url = url_for('index')
            return redirect(url)
        else:
            return render_template('login.html',error='用户名或密码错误!')


@app.route('/',methods=['GET'],endpoint='index')
def index():
    '''
    methods:请求方法
    endpoint:别名
    :return:
    '''
    return render_template('index.html',user_dict = USERS)


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

if __name__ == '__main__':
    app.run()
基于请求拓展中间件的登陆验证
from flask import Flask,render_template
app = Flask(__name__)
app.debug = True  # 开启调试模式


@app.before_first_request
def before_first_request1():
    print('仅第一次执行1')


@app.before_request  # 请求之前1
def process_request1(*args,**kwargs):
    print('请求之前1')
    return None


@app.before_first_request
def before_first_request2():
    print('仅第一次执行2')


@app.before_request  # 请求之前2
def process_request2(*args,**kwargs):
    # 设置白名单
    print('请求之前2')
    return None


@app.after_request  # 请求之后1
def process_response1(response):
    # return '拦截'
    print('请求之后1')
    return response


@app.after_request  # 请求之后2
def process_response2(response):
    # return '拦截'
    print('请求之后2')
    return response


@app.errorhandler(404)
def error_404(arg):
    return "根据状态码来定制404错误"


@app.template_global()
def sb(a1, a2):
    # 模板中定制方法
    return a1 + a2


@app.template_filter()
def db(a1, a2, a3):
    # 模板中定制方法
    return a1 + a2 + a3


@app.route('/',methods=['GET'],endpoint='index')
def index():
    print('index函数')
    return render_template('s2.html')


if __name__ == '__main__':
    app.run()
请求拓展方法
注意执行顺序:@app.before_first_request>@app.before_request>@app.after_request
其中多个@app.before_request按照先后顺序执行,多个@app.after_request按照倒叙执行


@app.errorhandler(状态码)  可以定制状态展示信息

@app.template_global()
def sb(a1, a2):
    # 模板中定制方法
    return a1 + a2

前端调用方式 {{sb(1,2)}}

@app.template_filter()
def db(a1, a2, a3):
    # 模板中定制方法
    return a1 + a2 + a3

前端调用方式 {{ 1|db(2,3)}}
from flask import Flask

app = Flask(__name__)
app.secret_key = 'password_key'


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


class MiddleWare:
    def __init__(self, old_wsgi_app):
        self.old_wsgi_app = old_wsgi_app

    def __call__(self, *args, **kwargs):
        print(args,kwargs)
        print('请求前的拓展')
        ret =  self.old_wsgi_app(*args, **kwargs)
        print('请求后的拓展')
        return ret


if __name__ == "__main__":
    # 重写app.wsgi_app
    app.wsgi_app = MiddleWare(app.wsgi_app)
    app.run()
中间件的拓展方式二

十、Flask插件

  1. WTForms    
  2. SQLAchemy
  3. 等...    http://flask.pocoo.org/extensions/

十一、装饰器小知识

方法一:注意注意!!!flask用装饰器如果没有导入functools模块来使用@functools.wraps(func)方法保存元类信息,每个函数中的endpoint必须指定别名,否则装饰后的每个函数别名将使用装饰器函数来命名,这样将导致程序报错

from flask import Flask,render_template,request,redirect,session,url_for
app = Flask(__name__)
app.debug = True  # 开启调试模式
app.secret_key='password_key' # 使用session必须设置secret_key密钥
'''
templates:默认模板文件夹名称
render_template:渲染页面方法
request:请求
redirect:跳转页面
session:session操作
url_for:url别名
'''


def auth(func):
    def inner(*args, **kwargs):
        user = session.get('user_info')
        if not user:
            return redirect('/login')
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result
    return inner


@app.route('/login',methods=['GET','POST'])
def login():
    if request.method=='GET':

        return render_template('login.html')
    else:
        # query_string--url里所有得数据
        # request.query_string
        # form--请求体里的数据
        user = request.form.get('user')
        pwd = request.form.get('pwd')

        if user=='admin' and pwd=='123456':
            session['user_info'] = user
            # 使用url_for反向生成/index
            url = url_for('index')
            return redirect(url)
        else:
            return render_template('login.html',error='用户名或密码错误!')


USERS = {
    1:{'name':'小明','age':'18','gender':'','text':'我是一个大暖男1'},
    2:{'name':'小黑','age':'19','gender':'','text':'我是一个大美女2'},
    3:{'name':'小白','age':'28','gender':'','text':'我是一个大暖男3'},
}


@app.route('/index',methods=['GET'],endpoint='index')
@auth
def index():
    '''
    methods:请求方法
    endpoint:别名
    :return:
    '''
    return render_template('index.html',user_dict = USERS)


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

if __name__ == '__main__':
    app.run()
装饰器1

方式二:导入functools模块来使用@functools.wraps(func)方法保存元类信息

import functools


def auth(func):
    @functools.wraps(func) # 帮助我们设置函数元信息 返回f1 否则返回inner
    def inner(*args, **kwargs):
        print('before')
        result = func(*args, **kwargs)
        print('after')
        return result
    return inner

@auth
def f1():
    pass

print(f1.__name__)
装饰器2

十二、Flask 上下文管理

import threading

local_values = threading.local()


def func(num):
    local_values.name = num
    import time
    time.sleep(1)
    print(local_values.name, threading.current_thread().name)


for i in range(20):
    th = threading.Thread(target=func, args=(i,), name='线程%s' % i)
    th.start()
本地线程,保证即使是多个线程,但是不支持协程,自己的值也是互相隔离。

 

更多...

 

posted @ 2019-01-28 14:33  我在地球凑人数的日子  阅读(115)  评论(0)    收藏  举报