快乐学习
前程无忧、中华英才非你莫属!

Flask入门到精通-Day1

前言
   
Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。
Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。
 
一、安装
我们推荐使用最新版本的 Python 3 。 Flask 支持 Python 3.4 及更高版本的 Python 3 、 Python 2.7 和 PyPy 。
1、安装python
安装Python3.7,下载windows安装包,一路next安装到C:python37。

2、创建环境
这里我说下python是如何安类库的,因安装类库比较方便的是直接在线安装,因官方安装源被国内墙了,且因地域的问题,经常出现timeout,这里面我们来配置国内的源来进行快速进行在线安装python的类库。
pip install -i https://pypi.douban.com/simple/ virtualenv     
pip install -i https://pypi.douban.com/simple/ virtualenvwrapper-win    
linux版本 pip install -i https://pypi.douban.com/simple/ virtualenvwrapper
设置WORKON_HOME环境变量 :E:virtualenv     
执行虚拟环境搭建
mkvirtualenv --python=C:python37python.exe py37
查看安装的所有虚拟环境:workon
进入虚拟环境:workon py37
退出虚拟环境:deactivate
接下来我们用独立环境py37 安装flask
workon py37
pip install Flask
如果想要在正式发行之前使用最新的 Flask 开发版本,可以使用如下命令从主分支 安装或者更新代码:



二、HelloWorld
HelloWorld
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello World!'
if __name__ == '__main__':
    app.run()
首先我们导入了 Flask 类。 该类的实例将会成为我们的 WSGI 应用。
接着我们创建一个该类的实例。第一个参数是应用模块或者包的名称。如果你使用 一个单一模块(就像本例),那么应当使用 __name__ ,因为名称会根据这个 模块是按应用方式使用还是作为一个模块导入而发生变化(可能是 ‘__main__’ , 也可能是实际导入的名称)。这个参数是必需的,这样 Flask 才能知道在哪里可以 找到模板和静态文件等东西。更多内容详见 Flask 文档。然后我们使用 route() 装饰器来告诉 Flask 触发函数的 URL 。
函数名称被用于生成相关联的 URL 。函数最后返回需要在用户浏览器中显示的信息。
把它保存为 hello.py 或其他类似名称。请不要使用 flask.py 作为应用名称,这会与 Flask 本身发生冲突。
可以使用 flask 命令或者 python 的 -m 开关来运行这个应用。在 运行应用之前,需要在终端里导出 FLASK_APP 环境变量:
$ export FLASK_APP=hello.py
$ flask run
开启Debug模式
app.run(debug=1)  开启调试模式,代码修改,保存之后服务器自动重启。



三、路由
现代 web 应用都使用有意义的 URL ,这样有助于用户记忆,网页会更得到用户的青睐, 提高回头率。
使用 route() 装饰器来把函数绑定到 URL:
@app.route('/who')
def hello():
    return 'ztloo'
url 变量操作
 <username>  尖括号里面的值=函数里面的 username  = 返回值 %右面的 username ,这样url里面的尖括号里面的变量就可以传递给函数,再由函数传递给返回值。
@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username
路由转换器:指定参数类型,就是只要在尖括号内指定类型,post后面的参数必须是哪个类型,如果是其他类型就会报错。
@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id
如果上述变量约束规则不够用,可以自定义正则转换器,下面实现custer 后面的参数必须是三个a到z的小写字母。
自定义转换器
class Regex_url(BaseConverter):
    def __init__(self, url_map, *args):
        super(Regex_url, self).__init__(url_map)
        self.regex = args[0]
# 将自定义转换器类添加到转换器字典中
app.url_map.converters['re'] = Regex_url
@app.route('/custer/<re("[a-z]{3}"):id>')
def hello_itheima(id):
    return 'hello %s' % id
唯一的 URL / 重定向行为
以下两条规则的不同之处在于是否使用尾部的斜杠。:
@app.route('/projects/')
def projects():
    return 'The project page'
@app.route('/about')
def about():
    return 'The about page'
projects 的 URL 是中规中举的,尾部有一个斜杠,看起来就如同一个文件夹。 访问一个没有斜杠结尾的 URL 时 Flask 会自动进行重定向,帮你在尾部加上一个斜杠。
about 的 URL 没有尾部斜杠,因此其行为表现与一个文件类似。如果访问这个 URL 时添加了尾部斜杠就会得到一个 404 错误。这样可以保持 URL 唯一,并帮助 搜索引擎避免重复索引同一页面。
例如,这里我们使用 test_request_context() 方法来尝试使用 url_for() 。 test_request_context() 告诉 Flask 正在处理一个请求,而实际上也许我们正处在交互 Python shell 之中, 并没有真正的请求。参见 本地环境 。
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/')
def index():
    return 'index'
@app.route('/login')
def login():
    return 'login'
@app.route('/user/<username>')
def profile(username):
    return '{}'s profile'.format(username)
with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='John Doe'))
/
/login
/login?next=/
/user/John%20Doe

四、HTTP方法、渲染模板、静态文件
Web 应用使用不同的 HTTP 方法处理 URL 。当你使用 Flask 时,应当熟悉 HTTP 方法。 缺省情况下,一个路由只回应 GET 请求。 可以使用 route() 装饰器的 methods 参数来处理不同的 HTTP 方法:
如果当前使用了 GET 方法, Flask 会自动添加 HEAD 方法支持,并且同时还会 按照 HTTP RFC 来处理 HEAD 请求。同样, OPTIONS 也会自动实现。
登陆demo
@app.route("/login",methods = ['GET', 'POST'])
def login():
    if request.method == "POST":
        username = request.form.get('username')
        password = request.form.get('password')
        if username=="zhangsan" and password=="123":
            return "<h1>welcome, %s !</h1>" %username
        else:
            return "<h1>login Failure !</h1>"
    else:
        return login_index()
@app.route("/show_login")
def login_index():
    return render_template("login_index.html")
login_index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<html>
<head>
    <title>login</title>
</head>
<body>
<form action="/login" method="post">
    username: <input type="text" name="username">
    password: <input type="password" name="password">
    <input type="submit" id="submit">
</form>
</body>
</html>
渲染模板详解
在 Python 内部生成 HTML 不好玩,且相当笨拙。因为你必须自己负责 HTML 转义, 以确保应用的安全。因此, Flask 自动为你配置 Jinja2 模板引擎。
官方demo
@app.route('/rt/')
@app.route('/rt/<name>')
def rtDemo(name=None):
    return render_template('rt.html', name=name)
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}
博客demo:
渲染模板:
1、静态页面模板放在templates文件夹中
2、需要导入render_template
3、视图函数中使用render_template函数渲染模板本例中使用的是return render_template('index.html', **context)
4、传多个参数的时候可以使用字典的形式如本例中的context={}
5、html代码中参数使用{{}}进行引用  本例中是
    <p>用户名:{{ username }}</p>
    <p>年龄:{{ age }}</p>
6、传参数类,字典 请看本例中的person类以及context中的wwwurl字典
@app.route('/persioninfo')
def persion():
    class Person(object):
        Email = '1071235258@qq.com';
        time = time.time();
    dell=Person()
    context={
        'username':"ztloo",
        'age': "17",
        'gender': "男",
        'flag': "IT",
        'hero': "一哥",
        'person':dell,
        'wwwurl':{
            'baidu':'www.baidu.com',
            'google':'www.google.com'
        }
    }
    return render_template('persion.html', **context)
persion.html
<!DOCTYPE html>
<html lang="utf-8">
<head>
    <meta charset="UTF-8">
    <title>falsk勾搭html</title>
</head>
<body>
    这是一个简单的页面,falsk勾搭html
    <p style="color:#FF00FF">用户名:{{ username }}</p>
    <p>年龄:{{ age }}</p>
    <p style="color:#7B68EE">性别:{{ gender }}</p>
    <p>等级:{{ flag }}</p>
    <p style="color:#FF00FF">英雄:{{ hero }}</p>
<hr>
    <!--引用类中的参数-->
    <p style="color:#7B68EE"> 申请邮箱:{{person.Email}}</p>
    <p style="color:#FF00FF">申请时间:{{person.time }}</p>
<hr>
    <!--引用wwwurl字典中的参数,有两种形式-->
    <p style="color:#7B68EE">百度:{{wwwurl.baidu}}</p>
    <p style="color:#FF00FF">谷歌:{{wwwurl['google'] }}</p>
</body>
</html>

操作请求数据
对于 web 应用来说对客户端向服务器发送的数据作出响应很重要。在 Flask 中由全局 对象 request 来提供请求信息。如果你有一些 Python 基础,那么 可能 会奇怪:既然这个对象是全局的,怎么还能保持线程安全?答案是本地环境:
flask在接受到客服端发来的请求后,会将其中的请求参数根据数据类型的区别分别存储在request对象的属性当中,调用这些属性就可以获得相应的请求参数
属性
说明
类型
environ
底层的WSGI环境。
以下6种URL的资源目录属性
path
u'/π/page.html'
full_path
u'/π/page.html?x=y'
script_root
u'/myapplication'
url
base_url
url_root
accept_charsets
此客户端支持的charsets列表作为 CharsetAccept对象
accept_encodings
此客户接受的编码列表。HTTP术语中的编码是压缩编码,例如gzip。对于charsets看看 accept_charset
accept_languages
此客户端接受的语言列表作为 LanguageAccept对象
accept_mimetypes
此客户端支持的mimetypes列表作为 MIMEAccept对象
access_route
如果存在转发的头,则这是从客户端ip到最后一个代理服务器的所有IP地址的列表。
classmethod applicationf 
装饰一个函数作为响应者,接受请求作为第一个参数。这与responder()装饰器类似,但函数作为第一个参数传递请求对象,请求对象将自动关闭:
参数:  
  f - WSGI可调用以进行装饰
返回:  
  一个新的WSGI可调用
authorization
解析形式Authorization对象
blueprint
当前蓝图的名称
cache_control
RequestCacheControl用于输入缓存控制标头的对象
close
关闭此请求对象的关联资源。这将显式关闭所有文件句柄。您还可以在with语句中使用请求对象,该语句将自动关闭它。
content_encoding
Content-Encoding实体标题字段用作媒体类型的修饰符
content_length
Content-Length实体头字段以字节为单位指示实体主体的大小,或者在HEAD方法的情况下,指示在请求为GET时已发送的实体主体的大小。
content_md5
RFC 1864中定义的Content-MD5实体头字段是实体主体的MD5摘要,用于提供实体主体的端到端消息完整性检查(MIC)。(注意:MIC适用于检测传输中实体的意外修改,但不能抵御恶意攻击。
content_type
Content-Type entity-header字段指示发送给接收者的实体主体的媒体类型,或者在HEAD方法的情况下,指示在请求是GET时已经发送的媒体类型。
cookies
A dict与请求一起传输的所有cookie的内容
data
包含传入的请求数据作为字符串,以防它带有mimetype Werkzeug无法处理
date
Date general-header字段表示发起消息的日期和时间,与RFC 822中的orig-date具有相同的语义
dict_storage_class
endpoint
与请求匹配的端点。这与结合使用 view_args可用于重建相同或修改的URL。如果匹配时发生异常,则会出现异常None
files
MultiDict包含所有上传文件的对象。每个键files都是来自的名称 每个值都是一个Werkzeug 对象。<inputtype="file" name="">filesFileStorage
它基本上就像你从Python中知道的标准文件对象,区别在于它还有一个 save()可以将文件存储在文件系统上的函数。
请注意,files如果请求方法是POST,PUT或PATCH以及<form>发布到 请求的方法则只包含数据enctype="multipart/form-data"否则它将是空的。
form
表单参数。默认情况下 ImmutableMultiDict ,从此函数返回。可以通过设置parameter_storage_class为其他类型来更改此设置 如果表单数据的顺序很重要,则可能需要这样做。
请记住,文件上传不会在此处结束,而是在files属性中结束。
form_data_parser_class
classmethod from_values* args** kwargs 
根据提供的值创建新的请求对象。如果给出了环境,则从那里填充缺失值。当您需要模拟来自URL的请求时,此方法对小脚本很有用。不要使用此方法进行单元测试,有一个功能齐全的客户端对象(Client),允许创建多部分请求,支持cookie等。
返回:请求对象
get_datacache = Trueas_text = Falseparse_form_data = False 
这会将来自客户端的缓冲传入数据读入一个字节串。默认情况下,这是缓存的,但可以通过将缓存设置False来更改该行为
如果表单数据已经被解析,
则此方法不会返回任何内容。 如果as_text设置为True,则返回值将是解码的unicode字符串
get_jsonforce = Falsesilent = Falsecache = True 
解析并将数据作为JSON返回
参数:
  • force - 忽略mimetype并始终尝试解析JSON。
  • 沉默 - 沉默解析错误并返回None 。
  • cache - 存储已解析的JSON以返回后续调用。
headers
来自WSGI环境的头文件是不可变的 EnvironHeaders
host
只有主机包括端口(如果有)
host_url
只是作为IRI计划的主机。另见:trusted_hosts
if_match
包含If-Match标头中所有etags的对象
if_modified_since
已解析的If-Modified-Since标头为datetime对象。
if_none_match
包含If-None-Match标头中所有etags的对象
if_range
解析的If-Range标头。
if_unmodified_since
已解析的If-Unmodified-Since标头为datetime对象
is_json
检查mimetype是否指示JSON数据, application / jsonapplication / * + json
is_multiprocess
boolean 如果应用程序由生成多个进程的WSGI服务器提供,则为True
is_multithread
boolean 如果应用程序由多线程WSGI服务器提供,则为True
is_run_once
boolean 如果应用程序在进程生命周期中只执行一次,则为True例如,CGI就是这种情况,但不保证执行只发生一次。
is_secure
如果请求是安全的,则为True
is_xhr
如果请求是通过JavaScript XMLHttpRequest触发的,则为True。这仅适用于支持X-Requested-With 标头的并将其设置为“XMLHttpRequest”。这样做的库是原型,jQuery和Mochikit,可能还有更多。
json
如果mimetype指示JSON(application / json,请参阅is_json()),这将包含已解析的JSON数据,否则它将是None
list_storage_class
make_form_data_parser
创建表单数据解析器。form_data_parser_class使用一些参数实例化 
max_content_length
MAX_CONTENT_LENGTH配置密钥的只读视图
max_forwards
Max-Forwards请求标头字段提供了一种TRACE和OPTIONS方法的机制,用于限制可以将请求转发到下一个入站服务器的代理或网关的数量。
method
请求方法。(例如'GET''POST')。
mimetype
喜欢content_type,但没有参数(例如,没有字符集,类型等)并且总是小写的
mimetype_params
mimetype参数为dict。例如,如果内容类型是params将是 text/html; charset=utf-8{'charset': 'utf-8'}
on_json_loading_failede 
如果get_json()解析失败并且未被静音,则调用如果此方法返回一个值,则将其用作返回值 get_json()默认实现引发 BadRequest异常。
parameter_storage_class
pragma
Pragma general-header字段用于包括可能适用于请求/响应链中任何收件人的特定于实现的指令
query_string
URL参数为raw bytestring
range
解析的Range标头
referrer
Referer [sic] request-header字段允许客户端为服务器的好处指定从中获取Request-URI的资源的地址(URI)(“referrer”,尽管头字段拼写错误)。
remote_addr
客户端的远程地址
remote_user
如果服务器支持用户身份验证,并且脚本受到保护,则此属性包含用户已通过身份验证的用户名
routing_exception=null
如果匹配URL失败,则这是在请求处理过程中引发/引发的异常。这通常是一个NotFound例外或类似的东西。
scheme
URL方案(http或https)
stream
如果传入的表单数据未使用已知的mimetype进行编码,则数据将在此流中未经修改地存储以供使用。大多数情况下,最好使用data哪种方式将数据作为字符串。流只返回一次数据。
user_agent
当前的用户代理。
url_rule=无
与请求匹配的内部URL规则。这可以用于检查来自前/后处理程序(request.url_rule.methods)等的URL允许哪些方法
values
view_args=无 
与请求匹配的视图参数的字典。如果匹配时发生异常,则会出现异常None
want_form_data_parsed
如果请求方法携带内容,则返回True
上传
已上传的文件被储存在内存或文件系统的临时位置。你可以通过请求对象 files 属性来访问上传的文件。每个上传的文件都储存在这个 字典型属性中。这个属性基本和标准 Python file 对象一样,另外多出一个 用于把上传文件保存到服务器的文件系统中的 save() 方法。
pip install flask-uploads
pip install flask_wtf
app.config['SECRET_KEY'] = 'I have a dream'
app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd()
photos = UploadSet('photos', IMAGES)
configure_uploads(app, photos)
patch_request_class(app)  # set maximum file size, default is 16MB
class UploadForm(FlaskForm):
    photo = FileField(validators=[
        FileAllowed(photos, u'只能上传图片!'),
        FileRequired(u'文件未选择!')])
    submit = SubmitField(u'上传')
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    form = UploadForm()
    if form.validate_on_submit():
        filename = photos.save(form.photo.data)
        file_url = photos.url(filename)
    else:
        file_url = None
    return render_template('upload.html', form=form, file_url=file_url)
upload.html
<!DOCTYPE html>
<title>Upload File</title>
<h1>图片上传</h1>
<form method="POST" enctype="multipart/form-data">
     {{ form.hidden_tag() }}
     {{ form.photo }}
     {% for error in form.photo.errors %}
         <span style="color: red;">{{ error }}</span>
     {% endfor %}
     {{ form.submit }}
</form>
{% if file_url %}
<img src="{{%20file_url%20}}">
{% endif %}

Cookies

要访问 cookies ,可以使用 cookies 属性。可以使用响应 对象 的 set_cookie 方法来设置 cookies 。请求对象的 cookies属性是一个包含了客户端传输的所有 cookies 的字典。在 Flask 中,如果使用 会话 ,那么就不要直接使用 cookies ,因为 会话 比较安全一些。
读取 cookies:
from flask import request
@app.route('/')def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.
储存 cookies:
from flask import make_response
@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp
注意, cookies 设置在响应对象上。通常只是从视图函数返回字符串, Flask 会把它们 转换为响应对象。如果你想显式地转换,那么可以使用 make_response() 函数,然后再修改它。
使用 延迟的请求回调 方案可以在没有响应对象的情况下设置一个 cookie 。
同时可以参见 关于响应 

 
重定向和错误
使用 redirect() 函数可以重定向。使用 abort() 可以 更早退出请求,并返回错误代码:
from flask import abort, redirect, url_for
@app.route('/')
def index():
    return redirect(url_for('login'))
@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()
上例实际上是没有意义的,它让一个用户从索引页重定向到一个无法访问的页面(401 表示禁止访问)。但是上例可以说明重定向和出错跳出是如何工作的。
缺省情况下每种出错代码都会对应显示一个黑白的出错页面。使用 errorhandler() 装饰器可以定制出错页面:
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404
注意 render_template() 后面的 404 ,这表示页面对就的出错 代码是 404 ,即页面不存在。缺省情况下 200 表示:一切正常。
详见 错误处理 

关于响应

视图函数的返回值会自动转换为一个响应对象。如果返回值是一个字符串,那么会被转换 为一个包含作为响应体的字符串、一个 200 OK 出错代码 和一个 text/html 类型的响应对象。以下是转换的规则:
  1. 如果视图返回的是一个响应对象,那么就直接返回它。
  2. 如果返回的是一个字符串,那么根据这个字符串和缺省参数生成一个用于返回的 响应对象。
  3. 如果返回的是一个元组,那么元组中的项目可以提供额外的信息。元组中必须至少 包含一个项目,且项目应当由(response, status, headers) 或者 (response, headers) 组成。 status 的值会重载状态代码, headers 是一个由额外头部值组成的列表或字典。
  4. 如果以上都不是,那么 Flask 会假定返回值是一个有效的 WSGI 应用并把它转换为 一个响应对象。
如果想要在视图内部掌控响应对象的结果,那么可以使用 make_response() 函数。
设想有如下视图:
@app.errorhandler(404)
def not_found(error):
        return render_template('error.html'), 404
可以使用 make_response() 包裹返回表达式,获得响应对象,并对该对象 进行修改,然后再返回:
@app.errorhandler(404)
def not_found(error):
        resp = make_response(render_template('error.html'), 404)
        resp.headers['X-Something'] = 'A value'
        
    return resp

会话

除了请求对象之外还有一种称为 session 的对象,允许你在不同请求 之间储存信息。这个对象相当于用密钥签名加密的 cookie ,即用户可以查看你的 cookie ,但是如果没有密钥就无法修改它。
使用会话之前你必须设置一个密钥。举例说明:
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
# Set the secret key to some random bytes. Keep this really secret!app.secret_key = b'_5#y2L"F4Q8znxec]/'
@app.route('/')def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''        <form method="post">            <p><input type=text name=username>            <p><input type=submit value=Login>        </form>    '''
@app.route('/logout')def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))
这里用到的 escape() 是用来转义的。如果不使用模板引擎就可以像上例 一样使用这个函数来转义。
如何生成一个好的密钥
生成随机数的关键在于一个好的随机种子,因此一个好的密钥应当有足够的随机性。 操作系统可以有多种方式基于密码随机生成器来生成随机数据。使用下面的命令 可以快捷的为 Flask.secret_key ( 或者 SECRET_KEY )生成值:
$ python -c 'import os; print(os.urandom(16))'
b'_5#y2L"F4Q8znxec]/'
基于 cookie 的会话的说明: Flask 会取出会话对象中的值,把值序列化后储存到 cookie 中。在打开 cookie 的情况下,如果需要查找某个值,但是这个值在请求中 没有持续储存的话,那么不会得到一个清晰的出错信息。请检查页面响应中的 cookie 的大小是否与网络浏览器所支持的大小一致。
除了缺省的客户端会话之外,还有许多 Flask 扩展支持服务端会话。

消息闪现

一个好的应用和用户接口都有良好的反馈,否则到后来用户就会讨厌这个应用。 Flask 通过闪现系统来提供了一个易用的反馈方式。闪现系统的基本工作原理是在请求结束时 记录一个消息,提供且只提供给下一个请求使用。通常通过一个布局模板来展现闪现的 消息。
flash() 用于闪现一个消息。在模板中,使用 get_flashed_messages() 来操作消息。完整的例子参见 消息闪现 

日志

Changelog
有时候可能会遇到数据出错需要纠正的情况。例如因为用户篡改了数据或客户端代码出错 而导致一个客户端代码向服务器发送了明显错误的 HTTP 请求。多数时候在类似情况下 返回 400 Bad Request 就没事了,但也有不会返回的时候,而代码还得继续运行 下去。
这时候就需要使用日志来记录这些不正常的东西了。自从 Flask 0.3 后就已经为你配置好 了一个日志工具。
以下是一些日志调用示例:
app.logger.debug('A value for debugging')app.logger.warning('A warning occurred (%d apples)', 42)app.logger.error('An error occurred')

 

logger 是一个标准的 Logger Logger 类, 更多信息详见官方的 logging 文档 
更多内容请参阅 应用错误处理 

集成 WSGI 中间件

如果想要在应用中添加一个 WSGI 中间件,那么可以包装内部的 WSGI 应用。假设为了 解决 lighttpd 的错误,你要使用一个来自 Werkzeug 包的中间件,那么可以这样做:
from werkzeug.contrib.fixers import LighttpdCGIRootFixapp.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)

 

使用 Flask 扩展
扩展是帮助完成公共任务的包。例如 Flask-SQLAlchemy 为在 Flask 中轻松使用 SQLAlchemy 提供支持。
更多关于 Flask 扩展的内容请参阅 扩展 

部署到网络服务器

已经准备好部署你的新 Flask 应用了?请移步 部署方式 
打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Flask入门到精通-Day1

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!