Flask(一)

2023-11-19

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:\Windows\System32\drivers\etc\hosts
    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()

 


 

 

转载于:https://www.cnblogs.com/sima-3/p/11600539.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flask(一) 的相关文章

  • Conda 无法在 Powershell 中激活

    我已经在我的 Windows 10 笔记本电脑上安装了 anaconda 我正在尝试激活名为的Python环境pyenv 首先 我检查conda env list在我的笔记本电脑中 这是 powershell 上的输出 PS C Users
  • uwsgi + Django REST框架:空闲时间后很少有缓慢的请求

    我正在运行 Django REST 框架 白天每分钟的请求率相当低 我注意到一个我无法解释或重现的问题 每天 在夜间或清晨 当我的 RPM 接近于零时 我会收到 1 10 个超慢的请求 我的平均响应时间100 到 200 毫秒之间 但是这个
  • 嵌套重组 - Django

    我有一个包含以下字段的模型 日期 员工 和 计划时间 每个员工对于不同的日期都有不同的计划工作时间 我正在尝试构建我的模板 其中员工按行列出 他们的计划工作时间列在正确的相应日期下的列中 像这样的东西 https i stack imgur
  • 提高 pytesseract 从图像中正确识别文本的能力

    我正在尝试使用读取验证码pytesseract模块 大多数时候它都能提供准确的文本 但并非总是如此 这是读取图像 操作图像以及从图像中提取文本的代码 import cv2 import numpy as np import pytesser
  • Python 包?

    好吧 我认为无论我做错了什么 它可能都是显而易见的 但我无法弄清楚 我已经阅读并重新阅读了有关包的教程部分 我唯一能想到的是这不起作用 因为我直接执行它 这是目录设置 eulerproject init py euler1 py euler
  • 解析器生成

    我正在做一个项目软件抄袭检测 我打算用C语言来做这件事 因为我应该创建一个令牌生成器和一个解析器 但我不知道从哪里开始 任何人都可以帮助我解决这个问题 我创建了一个令牌数据库 并将令牌与我的程序分开 接下来我想做的就是比较两个程序以查明它是
  • 定义Python字典时,如何使用给定字段的值来计算其他字段?

    考虑代码 a 2 b 3 mylist a a b b product a b 这会生成一个包含三个字段的字典 其中第三个字段是使用第一个和第二个字段的值计算的 我正在寻找更紧凑的定义mylist 我已经尝试过 1 mylist a 2 b
  • 使用 string.whitespace 删除 Python 中的空格

    Python 的 string whitespace 很棒 gt gt gt string whitespace t n x0b x0c r 如何在不手动输入 t n 等正则表达式的情况下将其与字符串一起使用 例如 它应该能够转动 请不要伤
  • 如何告诉杰克逊在反序列化期间忽略空对象?

    在反序列化过程中 据我理解是将JSON数据转换为Java对象的过程 我如何告诉Jackson 当它读取不包含数据的对象时 应该忽略它 我正在使用 Jackson 2 6 6 和 Spring 4 2 6 我的控制器收到的JSON数据如下 i
  • 为什么 PySpark 中的 agg() 一次只能汇总 DataFrame 的一列? [复制]

    这个问题在这里已经有答案了 对于下面的数据框 df spark createDataFrame data Alice 4 300 Bob 7 677 schema name High 当我尝试找到最小值和最大值时 我只得到输出中的最小值 d
  • Python Pandas groupby、排名,然后根据自定义排名分配值

    问题设置 大熊猫数据框 df pd DataFrame Group A A A A A A A A A Subgroup Group 1 Group 1 Group 1 Group 1 Group 1 Group 1 Group 2 Gro
  • Seaborn 条形图条之间没有空格

    我使用下面的代码创建了一个 Seaborn 条形图 它来自https www machinelearningplus com plots top 50 matplotlib visualizations the master plots p
  • Python Pandas:将参数传递给 agg() 中的函数

    我试图通过使用不同类型的函数和参数值来减少 pandas 数据框中的数据 但是 我无法更改聚合函数中的默认参数 这是一个例子 gt gt gt df pd DataFrame x 1 np nan 2 1 y a a b b gt gt g
  • 默认可变参数的惯用方式

    在 python 中 如果直接将可变类型设置为默认参数 则会出现众所周知的边缘情况 def foo x return x y foo y append 1 print foo 通常的解决方法是将参数默认为None然后将其放入体内 然而 有
  • 解释 scipy.stats.entropy 值

    我正在尝试使用scipy stats 熵来估计库尔巴克 莱布勒 KL 两个分布之间的散度 更具体地说 我想使用 KL 作为衡量标准来确定两个分布的一致性 但是 我无法解释 KL 值 例如 t1 numpy random normal 2 5
  • 在 d3v4 堆积条形图中使用 JSON

    我找到了一个d3v3堆积条形图示例 http bl ocks org mstanaland 6100713我想使用它 因为它使用 json 数据 还有一个d3v4规范条形图示例 https bl ocks org mbostock 3886
  • 将 numpy 记录数组转换为字典列表的有效方法

    如何转换下面的 numpy 记录数组 recs Bill 31 260 0 Fred 15 145 0 r rec fromrecords recs names name age weight formats S30 i2 f4 到字典列表
  • 来自 geoJSON 的 Google 地图航点

    我想从 geoJSON 文件加载行程 目前来说 它是有效的 但只有两点 但我需要添加 4 或 5 个航路点 我的代码只读取前两个点并将它们设置为起点和目的地 这是我的代码 google maps event addListener map
  • PyTorch 中的交叉熵

    交叉熵公式 但为什么下面给出loss 0 7437代替loss 0 since 1 log 1 0 import torch import torch nn as nn from torch autograd import Variable
  • 如何从 Python 脚本捕获 Curl 的输出

    我想使用curl查找有关网页的信息 但在Python中 到目前为止我有这个 os system curl head www google com 如果我运行它 它会打印出 HTTP 1 1 200 OK Date Sun 15 Apr 20

随机推荐

  • 一位数组返回id和pid通过这两个参数转换为树形结构数据,和树形结构的渲染

    废话不多说直接上代码 html代码我是引用了一个jq的插件作为样式插件名字为 jOrgChart 具体内容大家可以评论到下方 div class com div class TheEditor 编辑 div div div div js代码
  • Java 实体设置指定日期格式

    import com fasterxml jackson annotation JsonFormat JsonFormat pattern yyyy MM dd HH mm ss timezone GMT 8 private Date cr
  • nginx 代理图片服务器

    location gif jpg jpeg png expires 24h root home sk ftp 指定图片存放路径 proxy store on proxy store access user rw group rw all r
  • MATLAB BP神经网络 笔记整理

    1 如何更改输出层的激活函数 传递函数 对于有两层神经网络结构 可以通过调用以下函数 net layers 1 or 2 transferFcn for the hidden net layers 3 transferFcn for the
  • C#实现遍历文件夹获取指定后缀名文件

    问题描述 项目需要 要进行某文件夹下所有shp数据的读取 解决方法 using System using System Collections Generic using System ComponentModel using System
  • Python机器学习/数据挖掘项目实战 波士顿房价预测 回归分析

    Python机器学习 数据挖掘项目实战 波士顿房价预测 回归分析 此数据源于美国某经济学杂志上 分析研究波士顿房价 Boston HousePrice 的数据集 在这个项目中 你将利用马萨诸塞州波士顿郊区的房屋信息数据训练和测试一个模型 并
  • Qt之一个类成员函数调用另一个类成员的方法

    原文 https blog csdn net qq 35721743 article details 83592415 在继承之外 在C 中一个类成员函数调用另一个类成员的方法主要有 类的组合 友元类 类的前向声明 单例模式等 下面主要讲讲
  • gym 101512 BAPC 2014 I Interesting Integers

    Problem codeforces com gym 101512 attachments vjudge net contest 186506 problem I Meaning 给出一个 正整数 n 要找尽量小的 a 和 b a lt b
  • 面向对象三大特性之一——多态详解

    目录 前言 一 多态的概念 二 多态的定义及实现 1 虚函数的概念 2 虚函数的重写 2 1概念 2 2虚函数重写的两个例外 3 多态的构成条件 4 c 11 override和final 4 1 final 4 2 override 5
  • Java(五)-Java集合(comparable,map,list

    集合 Collection集合 集合的概念 ArrayList就是一个集合 集合是Java提供的一种容器 可以用来存储多个数据 集合与数组的区别 1 数组的长度是固定的 集合的长度是可变的 2 数组中存储的是同一类型的元素 可以存储基本数据
  • C++ 和 C 使用的不同点(待定)

    1 结构体 C 中定义的结构体 不起别名的情况下使用时要添加 struct C 可以不用添加 struct 直接使用定义的结构体名称 struct Student int age char name C 不报错 C报错 Student Ge
  • JDK的监听 Spring的事件监听机制

    一 概述 使用场景 用户注册完成时 需要给该用户发送邮件 发送优惠劵等等操作 实现业务的解耦 MQ的异步 销峰 解耦 大体步骤 1 UserService 在完成自身的用户注册逻辑之后 仅仅只需要发布一个 UserRegisterEvent
  • 归一化与反归一化在Bi-LSTM多特征时序预测中应用(附实操代码)

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 目录 前言 一 Bi LSTM 是什么 二 为什么要归一化和反归一化 1 归一化的好处 2 反归一化的好处 三 归一化和反归一化使用的公式 1 归一化 2 反归一化 四 实操
  • 使用Pandas处理Excel文件

    Excel工作表是非常本能和用户友好的 这使得它们非常适合操作大型数据集 即使是技术人员也不例外 如果您正在寻找学习使用Python在Excel文件中操作和自动化内容的地方 请不要再找了 你来对地方了 在本文中 您将学习如何使用Pandas
  • forkjoin及其性能分析,是否比for循环快?

    最近看了网上的某公开课 其中有讲到forkjoin框架 在这之前 我丝毫没听说过这个东西 很好奇是什么东东 于是 就顺道研究了一番 总感觉这个东西 用的地方很少 也有可能是我才疏学浅 好吧 反正问了身边一堆猿 没有一个知道的 因此 我也没有
  • 怎么把树莓派连接到电脑上(基于window10)

    我相信对于刚玩树莓派的新手来说 尤其是没有带显示屏的同学来说 四处碰壁 可能出现的原因有很多种 ssh登录不上 wifi连接不上 内存不足 很多问题 而对于更多新手来说 如何给树莓派连接网络更是关键 今天我给大家讲一下如何用树莓派连接电脑
  • Real-time Linux

    所谓实时操作系统 Real time Opearting System 是指当外接世界或数据产生时 能够接受并以足够快的速度予以处理 其处理的结果又能在规定的时间之内来控制生产过程或对处理系统做出快速响应 调度一切可利用的资源完成实时任务
  • 数据链路层:Ethernet以太网协议

    首先Ethernet IEEE802 3 PPP和HDLC都是数据链路层的协议 只不过后面三个不常用而已 Ethernet和IEEE802 3属于以太链路层协议 数据链路层最常用的协议是Etnernet以太网协议 定义 Ethernet以太
  • 常用的加密算法

    整理一下常用的加密算法 加密算法我们整体可以分为 可逆加密和不可逆加密 可逆加密又可以分为 对称加密和非对称加密 一 不可逆加密 常见的不可逆加密算法有MD5 HMAC SHA1 SHA 224 SHA 256 SHA 384 和SHA 5
  • Flask(一)

    Flask 0 Flask简介 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架 对于Werkzeug本质是Socket服务端 其用于接收http请求并对请求进行预处理 然后触发Fl