Flask(一)

摘要:
开发人员根据Flask框架提供的函数处理请求,并将呈现的字符串返回给用户浏览器。(micro)这并不意味着您需要将整个Web应用程序放入单个Python文件中(尽管这确实是可能的)。Flask不包括数据库抽象层和表单验证。许多扩展提供了数据库集成、表单验证、上载处理和各种开放身份验证技术等功能。
Flask

0.Flask简介

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

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

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

wsgiref

最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块

from wsgiref.simple_server import make_server

def mya(environ, start_response):
   print(environ)
   start_response('200 OK', [('Content-Type', 'text/html')])
   if environ.get('PATH_INFO') == '/index':
       with open('index.html','rb') as f:
           data=f.read()

   elif environ.get('PATH_INFO') == '/login':
       with open('login.html', 'rb') as f:
           data = f.read()
   else:
       data=b'<h1>Hello, web!</h1>'
   return [data]

if __name__ == '__main__':
   myserver = make_server('', 8011, mya)
   print('监听8010')
   myserver.serve_forever()

wsgiref简单应用

 

1.安装

pip3 install flask

2.werkzeug简介

Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等

代码示例:

from werkzeug.wrappers import Request, Response

@Request.application
def hello(request):
   return Response('Hello World!')

if __name__ == '__main__':
   from werkzeug.serving import run_simple
   run_simple('localhost', 4000, hello)

3.flask快速使用

from flask import Flask
# 实例化产生一个Flask对象
app = Flask(__name__)
# 将 '/'和视图函数hello_workd的对应关系添加到路由中
@app.route('/') # 1. v=app.route('/') 2. v(hello_world)
def hello_world():
    return 'Hello World!'if __name__ == '__main__':
    app.run() # 最终调用了run_simple()

4.配置文件

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.config['DEBUG'] = True
   PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)

方式二

#通过py文件配置
app.config.from_pyfile("python文件名称")
如:
settings.py
DEBUG = True
​
app.config.from_pyfile("settings.py")
#通过环境变量配置
app.config.from_envvar("环境变量名称")
#app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])
环境变量的值为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目录(Flask对象init方法的参数)

5.路由系统

典型写法

 @app.route('/detail/<int:nid>',methods=['GET'],endpoint='detail')

默认转换器

DEFAULT_CONVERTERS = {
   'default':          UnicodeConverter,
   'string':           UnicodeConverter,
   'any':              AnyConverter,
   'path':             PathConverter,
   'int':              IntegerConverter,
   'float':            FloatConverter,
   'uuid':             UUIDConverter,
}

路由系统本质

"""
1. decorator = app.route('/',methods=['GET','POST'],endpoint='n1')
    def route(self, rule, **options):
        # app对象
        # rule= /
        # options = {methods=['GET','POST'],endpoint='n1'}
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator
2. @decorator
    decorator(index)
"""
#同理
def login():
    return '登录'
app.add_url_rule('/login', 'n2', login, methods=['GET',"POST"])
#与django路由类似
#django与flask路由:flask路由基于装饰器,本质是基于:add_url_rule
#add_url_rule 源码中,endpoint如果为空,endpoint = _endpoint_from_view_func(view_func),最终取view_func.__name__(函数名)

基本用法总结:

启动flask
第一步
from flask import Flask
app=Flask(__name__)
第二步
@app.route("/")
def index():
    return "123"
第三步
app.run()

启动flask本质是执行
wsgi_app(ev,re)


django四剑客
'''
redirect--->redirect
HttpResponse---->""
render--->render_template 注意他的传值,必须字典打散
JsonResponse--->jsonify
'''

配置文件的四种方式
#第一种方式
# app.debug=True
# app.secret_key="asdas"
#第二种方式
# app.config["DEBUG"]=True
#第三种方式
# app.config.from_pyfile("settings.py")
#第四种方式(推荐)
app.config.from_object('settingss.Test')

flask路由本质
基于装饰器添加路由其实是执行:
app.add_url_rule(self, rule, endpoint=None, view_func=None)
rule--->路由
endpoint--->反向解析的别名
view_func---->当前的视图函数
methods ---->允许请求的方式["get","post"],如果不传默认允许的是get请求

怎样反向解析获取路由
url_for(别名)

严格模式:

from flask import Flask
app=Flask(__name__)

@app.route("/<int:nid>",strict_slashes=False)
def index(nid):
    print(nid)
    return "ok"


@app.route("/index",strict_slashes=True,redirect_to="/1")
def index1():

    return "ok1"

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

CBV(源码分析)

'''
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!' #如果不传name,这所有返回的都是view,这样就会报错,所有人家必须你要传递参数 #然后他传递给view_func的其实就是你视图类中的dispatch_request方法。这样我们没有办法,在一个视图类中写多种请求方式 app.add_url_rule('/index', view_func=IndexView.as_view(name='index')) # name=endpoint #或者,通常用此方式
方式二:
class IndexView(views.MethodView): methods = ['GET'] #cbv添加装饰,用这个,我们看as_view中就知道了,不写methods默认为GET请求 decorators = [auth, ] ​ def get(self): return 'Index.GET'def post(self): return 'Index.POST' #如果我们继承了MethodView,他帮我们重写了,dispatch_request方法,他给我们做了一个分发,通过请求,来执行不同的函数 app.add_url_rule('/index', view_func=IndexView.as_view(name='index')) # name=endpoint

app.add_url_rule参数

@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"]
#对URL最后的 / 符号是否严格要求
strict_slashes = None
    '''
        @app.route('/index', strict_slashes=False)
        #访问http://www.xx.com/index/ 或http://www.xx.com/index均可
        @app.route('/index', strict_slashes=True)
        #仅访问http://www.xx.com/index
    '''
#重定向到指定地址
redirect_to = None, 
    '''
        @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
    '''#子域名访问
subdomain = None, 
    '''
    #C:WindowsSystem32driversetchosts
    127.0.0.1       www.liuqingzheng.com
    127.0.0.1       admin.liuqingzheng.com
    127.0.0.1       buy.liuqingzheng.com
    
    from flask import Flask, views, url_for
    app = Flask(import_name=__name__)
    app.config['SERVER_NAME'] = 'liuqingzheng.com:5000'
    @app.route("/", subdomain="admin")
    def static_index():
        """Flask supports static subdomains
        This is available at static.your-domain.tld"""
        return "static.your-domain.tld"
    #可以传入任意的字符串,如传入的字符串为aa,显示为 aa.liuqingzheng.com
    @app.route("/dynamic", subdomain="<username>")
    def username_index(username):
        """Dynamic subdomains are also supported
        Try going to user1.your-domain.tld/dynamic"""
        return username + ".your-domain.tld"
    if __name__ == '__main__':
        app.run()
        
    访问:
    http://www.liuqingzheng.com:5000/dynamic
    http://admin.liuqingzheng.com:5000/dynamic
    http://buy.liuqingzheng.com:5000/dynamic
    '''

支持正则

#1 写类,继承BaseConverter
#2 注册:app.url_map.converters['regex'] = RegexConverter
# 3 使用:@app.route('/index/<regex("d+"):nid>')  正则表达式会当作第二个参数传递到类中
from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter
​
app = Flask(import_name=__name__)
​
class RegexConverter(BaseConverter):
    """
    自定义URL匹配正则表达式
    """
    def __init__(self, map, regex):
        super(RegexConverter, self).__init__(map)
        self.regex = regex
​
    def to_python(self, value):
        """
        路由匹配时,匹配成功后处理并传递给视图函数中参数的值
        """
        return int(value)
​
    def to_url(self, value):
        """
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
        """
        val = super(RegexConverter, self).to_url(value)
        return val
# 添加到flask中
app.url_map.converters['regex'] = RegexConverter
@app.route('/index/<regex("d+"):nid>')
def index(nid):
    print(url_for('index', nid='888'))
    return 'Index'if __name__ == '__main__':
    app.run()

案例:登录,显示用户信息 (模板)

from flask import Flask,render_template,request,redirect,url_for,Markup
app = Flask(__name__)
app.debug = True

# 模板渲染的时候
'''
模板里面
渲染变量
{{}}-->和django一样
{% for k,v in dict.item()%}
    {{v.name}}
    {{v.get("name")}}
    {{v['name']}}
{% endfor %}
'''
'''
methods=["GET","POST]
/detail/<int:nid> 
nid会当做参数传给我们的视图函数
我们给模板传值的必须是关键字传值
url_for()做反向解析,填的是endpoint的值,如果要跳转的视图没有指定endpoint,就用函数名

'''

USERS = {
    1:{'name':'张三','age':18,'gender':'','text':"道路千万条"},
    2:{'name':'李四','age':28,'gender':'','text':"安全第一条"},
    3:{'name':'王五','age':18,'gender':'','text':"行车不规范"},
}

@app.route('/detail/<int:nid>',methods=['GET'])
def detail(nid):

    info = USERS.get(nid)
    return render_template('detail.html',info=info)


@app.route('/index',methods=['GET'])
def index():


        # return redirect('/login')
    url = url_for('l1')
    return redirect(url)
    #return render_template('index.html',user_dict=USERS)


@app.route('/login',methods=['GET','POST'],endpoint='l1')
def login():
    if request.method == "GET":
        return render_template('login.html')
    else:
        # request.query_string
        user = request.form.get('user')
        pwd = request.form.get('pwd')
        if user == 'cxw' and pwd == '123':

            return redirect('http://www.baidu.com')
        return render_template('login.html',error='用户名或密码错误')

def func1(a,b):
    return Markup(f"<h1>蔡徐坤{a},{b}</h1>")



@app.route("/test")
def test():
    return render_template('test.html', error=func1)

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

templates / detail.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>详细信息 {{info['name']}}...{{info.get('name')}}....{{info.name}}</h1>
    <div>
        {{info.text}}
    </div>
</body>
</html>

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% for k,v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详细</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

login.html:

<!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="text" name="pwd">
        <input type="submit" value="登录">{{error}}
    </form>
</body>
</html>

test.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Title</title>
</head>
<body>
<!--{{error|safe}}-->
<!--{{error("666","ttt")}}-->
<!--<a>{{url_for("l1")}}</a>-->
1312
</body>
</html>

六.请求与响应

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

app = Flask(__name__)

'''
获取当前请求的内容
1 先要导入request
2 直接用request.方法,属性
返回的时候,如果需要设置额外的响应参数,比如cookie,heard
1 response=make_response(四剑客)
2 response.设置属性=“属性值”
3 return response

'''

@app.route('/login.html', methods=['GET', "POST"])
def login():

    # 请求相关信息
    # request.method  提交的方法
    print("request.method",request.method)
    # request.args  get请求提及的数据
    print("request.args", request.args)
    # request.form   post请求提交的数据
    # request.values  post和get提交的数据总和
    # request.cookies  客户端所带的cookie
    # request.headers  请求头
    # request.path     不带域名,请求路径
    # request.full_path  不带域名,带参数的请求路径
    # request.script_root
    # request.url           带域名带参数的请求路径
    # request.base_url        带域名请求路径
    # request.url_root      域名
    # request.host_url        域名
    # request.host            127.0.0.1:500
    # request.files
    # obj = request.files['the_file_name']
    # obj.save('/var/www/uploads/' + secure_filename(f.filename))

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

    # response = make_response(render_template('index.html'))
    # response是flask.wrappers.Response类型
    # response.delete_cookie('key')
    # response.set_cookie('key', 'value')
    # response.headers['X-Something'] = 'A value'
    # return response
    response1=make_response(render_template('rr.html'))
    #response1.set_cookie('key_sss', 'valuessbbsd')              设置cookie
    # response1.delete_cookie('key_sss')                         删除cookie
    response1.headers['sb'] = 'asdas'                            设置响应头
    return response1

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

rr.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Title</title>
</head>
<h1>qweqw</h1>
<body>

</body>
</html>

七.session (cookie键可通过配置文件修改,默认是session;value值是一个加密的字典)

from flask import Flask,session


app = Flask(__name__)
app.debug=True
app.secret_key="ajsdklas"
app.config['SESSION_COOKIE_NAME']="session_key"
# app.session_interface  查看源码
@app.route("/")
def index():
    session['name']="sb"
    return "ok"

@app.route("/test")
def test():
    print(session['name'])
    return "ok1"

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

app.session_interface中save_session的参数(设置cookie的参数)

key, 键
value='', 值
max_age=None, 超时时间 cookie需要延续的时间(以秒为单位)如果参数是 None`` ,这个cookie会延续到浏览器关闭为止
expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。
domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。如, domain=".example.com"所构造的cookie对下面这些站点都是可读的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果该参数设置为 None ,cookie只能由设置它的站点读取
secure=False, 浏览器将通过HTTPS来回传cookie
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

session源码的执行流程

-save_seesion
    -响应的时候,把session中的值加密序列化放大到了cookie中,返回到浏览器中
-open_session
    -请求来了,从cookie中取出值,反解,生成session对象,以后再视图函数中直接用sessoin就可以了。

八.闪现(message)

-设置:flash('aaa')
-取值:get_flashed_message()
-
-假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息
from flask import Flask,flash,get_flashed_messages,request,redirect

app = Flask(__name__)
app.debug=True
app.secret_key = 'asdfasdf'
'''
1 设置flash
    1.1 flash("要传递的值",category="分类的名称"),如果不传默认是message
    本质:session['_flash']
2取flash设置的值我们用get_flashed_messages
 2.1 get_flashed_messages(with_categories=False, category_filter=()),
    2.1.1如果不传递 category_filter,取出上面存储的所有分类传递的值
    2.1.2如果不传with_categories就只取值,不取分类的名字,如果传,就获取 分类名和分类值
    
3 这个flash只能一个视图函数中取,只要有一个视图函数取过了,那其他视图函数就不能获取
    本质:session.pop("_flash")
    3.1 但是在同一个视图函数里面可以无限的取值
   


'''

@app.route('/index')
def index():
    # 从某个地方获取设置过的所有值,并清除。
    #flash('超时错误',category="x1")
    flash("它过来了,你要小心")
    flash("我是第二个",category="ss")
    return "ssdsdsdfsd"
    # return redirect('/error')


@app.route('/error')
def error():
    """
    展示错误信息
    :return:
    如果get_flashed_messages(with_category=True)
    """
    #data = get_flashed_messages(category_filter=['x1'])
    data=get_flashed_messages(with_categories=True,category_filter=['ss'])
    data1 = get_flashed_messages(with_categories=True, category_filter=['ss'])
    print(type(data))
    print(data1)
    return "错误信息:%s" %(data,)


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

 九.请求扩展

from flask import Flask,render_template

app = Flask(__name__)
'''
1 before_request 请求之前
    1.1可写多个befor_request函数
    1.2而且是从上往下执行的
    1.3 一旦有返回值,请求的视图函数不会执行,已经剩下的befor_request不会执行
2 after_request 请求之后
    2.1可以写多个after_request函数
    2.2 所有的after_request是从下往上执行,和befor_request相反
    2.3 无论 befor_request有没有返回值,我的after_request都会执行
    2.4 必须接受response,而且必须返回response
    
3 before_first_request 是我项目启动后,接受到的第一个请求,会执行该函数,后面就不会在执行

4 teardown_request(e)
    4.1 这是e 是接收我服务器抛出的异常
    4.2 无论我服务器有没有错误,都会执行该函数
    4.3 虽然能接收异常,但是没有办法处理异常
    
5 errorhandler(500) 
    5.1 参数的中值为错误码
    5.2 当服务器抛出对应状态码的异常,就会执行该函数
    5.3 并且该函数可以处理异常,让用户无法感知,服务器错误
    5.4 每一个错误码,都需要一个对应的函数进行处理

'''


# app.debug=True



#基于它做用户登录认证
# @app.before_request
# def process_request():
#     print(request)
#     print("我是请求之前")
#     return "我回来了"
#
# @app.before_request
# def process_request1():
#     print("我是请求之前1")

#请求之后
# @app.after_request
# def process_response1(response):
#     print('process_response1 走了')

#     return response
# @app.after_request
# def afr(response):
#     print("23423")
#     return response
# @app.after_request
# def tt(response):
#     print("我是第一个")
#     return response

#项目接收的第一个请求
# @app.before_first_request
# def a():
#     print("我的第一次")

#如论有无异常都执行,如果没有异常这个e就是None
# @app.teardown_request
# def ter(e):
#     # if e:
#         #logingh
#     # return "wo si l"
#     print("我抛异常")
#
# #我不希望看到我的服务器错误,参数填写的是错误状态码
# @app.errorhandler(500)
# def error_500(arg):
#     print(arg)
#     return "请等一下在试"
#
# @app.errorhandler(404)
# def erros(arg):
#     print(arg)
#     return "你拨打的用户不存在"

@app.template_global()
def sb(a1, a2):
    return a1 + a2

@app.template_filter()
def db(a1, a2, a3):
    print(a1)
    print(a2)
    print(a3)
    return a1 + a2 + a3
#

@app.route('/')
def index():
    print("我是你要请求的函数")
    # a
    return render_template("gllo.html")




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

gllo.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Title</title>
</head>
<body>
{{sb(1,2)}}
{{ 1|db(2,3)}}
</body>
</html>

十.中间件:

from flask import Flask
app=Flask(__name__)
class MyMiddleware:
    def __init__(self,wsgi_app):
        self.wsgi_app_old=wsgi_app
    def __call__(self,environ, start_response):
        print("我的开始之前")
        res=self.wsgi_app_old(environ, start_response)
        print("我是所有的结束之后")
        return  res

@app.before_request
def a():
    print("我是请求之前")


@app.route("/")
def index():
    print("我是视图函数")
    return "ok"

if __name__ == '__main__':
    app.__call__
    '''
        def __call__(self, environ, start_response):
            print(ww)
            return self.wsgi_app(environ, start_response)
            print(asdas)
            
            
            print(ww)
            return self.wsgi_app(environ, start_response)
            print(asdas)
    
    '''
    app.wsgi_app = MyMiddleware(app.wsgi_app)#MyMiddleware的对象
    #新的app.wsgi_app
    #app.wsgi_app是MyMiddleware的对象
    #app.wsgi_app()
    #MyMiddleware的对象的__call__()
    #MyMiddleware.__call__

    app.run()

 

免责声明:文章转载自《Flask(一)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇安装django(使用国内镜像)用命令打开本地tomcat服务器下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

二级动态菜单的功能

二级动态菜单的实现, 我们可能需要一个  下方展示的这样的一种数据结构: { 1: { 'title': '用户管理', 'icon': 'fa fa-envira', 'children': [ {'title': '客户列表', 'url': '/customer/li...

HTML页面使用layer弹出框输入数据

javascript中layer是一款近年来备受青睐的web弹层组件,layer.open对弹出框进行输入信息,并处理返回结果。详细介绍http://layer.layui.com/部署:将layer.js文件和skin目录复制到项目的./static/js目录中,在页面中引用js/layer.js <script >function add_...

使用html2canvas和jsPdf实现打印功能

最近做项目中,️遇到过实现模版打印功能,网上也找到很多资料可以实现,有的方式可以实现分页,但是打印的A4纸上下不能留边距,后来找到一个通过剪裁的方式可以实现左右上下留边距,并且能实现分页; 方法如下:基本思路是对获得的canvas进行切割,按A4纸大小并留边距后的比例进行剪裁,切出一页一页的内容来,再分别加到pdf中。 DEMO: 1 // 导出页面为...

安卓app设计规范整理和Android APP设计篇(转)

随着安卓智能手机不停的更新换代。安卓手机系统越来越完美,屏幕尺寸也越来越大啦!比如最近小米的miui 6的发布和魅族手机系统的更新等等。 以小米MIUI6的安卓手机来说,MIUI6进行了全新设计,坚持“内容才是本质”的设计哲学,重新提炼内容,简化图标设计。 所以,我们在进行安卓APP设计时,需要好好调整之前的设计规范和设计细节。根据目前流行的安卓手机的系...

vue 之 ESLint学习(格式化操作)

  在vscode 的右下角 有一个eslint 可以控制 在vscode保存时对代码格式化存在的因素: 第一个因素:存在vscode插件的原因 第二个因素: 查看代码是否符合standar规范: https://standardjs.com/rules-zhcn.html 查看具体细则:https://cn.eslint.org/docs/rules/...

BUUCTF PWN [HarekazeCTF2019]baby_rop2

今天的最后一题 int __cdecl main(int argc, const char **argv, const char **envp) { char buf[28]; // [rsp+0h] [rbp-20h] BYREF int v5; // [rsp+1Ch] [rbp-4h] setvbuf(stdout, 0LL, 2,...