Flask1.0.2系列(三) 快速入门

英文原文地址:http://flask.pocoo.org/docs/1.0/quickstart/

若有翻译错误或者不尽人意之处,请指出,谢谢~


        看完之前的内容是否已经急不可耐地想入门学习Flask了?本文会是一个关于Flask很好的入门介绍。在这里假设你已经安装好了Flask。如果你没有安装Flask,推荐你看Flask系列(二)。


1. 一个简单的Flask程序

        简单的可运行的Flask程序如下所示:

from flask import Flask


app = Flask(__name__)


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

        这段简单的代码做了什么事呢?

        1. 首先,我们导入了Flask类。等会儿创建这个类的一个实例对象将会成为我们的WSGI应用程序。

        2. 接着我们创建上述的Flask类的实例对象。类的第一个形参代表应用程序模块或者包的名称。如果你仅仅使用了一个模块(就像这个示例代码一样),你可以直接使用__name__,因为__name__所表示的值是取决于这个模块是作为一个应用程序的开始还是作为一个导入的模块(即'__main__'与实际导入的名称)。这个是必须的,所以Flask知道在哪里去寻找模板(templates),哪里去寻找静态文件(static files)等等。更多详细的信息请查看Flask文档

        3. 当我们使用route()修饰符时,是为了告诉Flask什么URL能够触发该修饰符下的方法。

        4. 该函数还提供了一个名称用于为该特定函数生成URL,并且返回我们希望在用户的浏览器中显示的信息。

        现在保存上述代码在一个hello.py文件或者其他名称的文件中。但不要把文件命名为flask.py,因为这与Flask本身是冲突的。

        想要启动这个应用程序,你可以使用flask的命名或者python的-m转换到Flask上。在此之前,你需要导出环境变量FLASK_APP,来告诉终端这个应用程序是基于此工作的:

$ export FLASK_APP=hello.py
$ flask run
 * Running on http://127.0.0.1:5000/

        如果你是在Windows操作系统下,你需要使用set来代替export命令:

C:\path\to\app>set FLASK_APP=hello.py

        下面是在管理员权限下的shell:

PS C:\path\to\app> $env:FLASK_APP = "hello.py"

        另外,你可以使用python -m flask:

$ export FLASK_APP=hello.py
$ python -m flask run
 * Running on http://127.0.0.1:5000/

        这样可以实现一个非常简单的嵌入式的服务,用于测试的话这是足够的,但并不建议在实际项目中使用这种方式。关于部署的内容,请参见部署项一文。

        现在,在浏览器中访问http://127.0.0.1:5000/,你就能看到万年不变的“Hello, World!”页面了。

        非本机访问的服务:

        如果你运行了之前的服务,你可能会注意到这个服务只能被我们本机访问,网络中的其他机器并不能访问到这个服务。这是因为在调试模式下,应用程序的用户可以在本地机器上执行任意的Python代码,为了防止Python代码被篡改,因此默认服务只能被本机访问。

        如果你禁用了你的调试器,或者你信任你所处网络的所有用户,你可以在命令行中添加“--host=0,0,0,0”来将服务公开:

flask run --host=0,0,0,0

        这样做,会告诉你的操作系统将监听所有公开的IP来访问服务。


2. 若服务启动不了该怎么玩?

        有多种原因可能造成python -m flask命令失败或者flask不存在的情况。因此,你首先需要确定的是系统给出的错误信息。

2.1 Flask的版本太老了

        在Flask的0.11版本之前的版本有着不同的启动运用程序的方式。简单来说,也就是之前的版本不存在falsk命令,也不存在python -m flask。在这种条件下,你有两个选择:要么将Flask升级到最新的版本,要么去查询Flask对应版本的开发文档去查找对应的启动服务的方法。

2.2 不合法的导入名

        环境变量“FLASK_APP”是flask运行时导入的模块的名称。如果模块的名称是错误的,那么你会在程序开始的时候得到一个导入错误(如果当你导航到应用程序时,调试模式是开启的状态)。调试模式下,你会知道flask正在尝试导入什么,以及运行为什么会失败。

        最常见的原因是输入错误,或者实际上你并没有创建一个app对象。


3. 调试模式

        (想要记录错误日志,又想追踪错误?参见应用程序错误

        flask脚本能够很漂亮地运行一个本地服务,但是每次修改了代码后你又不得不手动重启服务来执行最新的代码。这一点并不是那么完美,但是flask可以解决这个小问题。如果你开启了调试模式,当代码变更时服务是可以重新加载的,如果出错的话,它还会将为你提供一个有用的调试器。

        想要开启调试模式,你需要在服务运行之前导出环境变量“FLASK_DEBUG”:

$ export FLASK_DEBUG=1
$ flask run

        (再次声明,在Windows操作系统,你需要使用set来替代export)

        这两条命令做了以下的事:

        1. 激活了调试器

        2. 激活了自动重新加载

        3. 在Flask应用程序开启了调试模式

        想要了解更多的参数解释,参见开发服务一文。

        注意:

        尽管交互式调试器不能在多进程环境下工作(这使得它在生产服务器上几乎是不可能使用的),但它依然允许执行任意代码。这使得交互式调试器成为一个主要的安全风险,因此它在生产机器上从来不被使用。

        调试器的屏幕截图如下:


        想要了解另外的调试器?请参阅与调试器协同工作


4. 路由

        现代的Web应用程序都拥有很多优雅的URL地址。这样做能帮助人们记住他们对应的URL地址,这对于那些使用缓慢的网络连接的可移动设备的应用程序来说尤其方便。如果用户能够直接跳转到他希望的页面,而不是通过索引页面跳转过去,那么他们肯定会非常喜欢这个页面,以至于下次他们还会继续访问这个页面。

        正如你上面所看到的,route()修饰符就是用来将一个方法绑定到一个URL上。这里有一些简单的示例:

@app.route('/')
def index():
    return 'Index Page'


@app.route('/hello')
def hello():
    return 'Hello, World'

        但我们想要说的不仅仅是这样。你可以让URL的某些部分变成动态的,并且你也可以在一个方法上附加一系列的规则。

4.1 可变规则

        为了使URL的某些部分变成可变的,你可以在URL中添加一些特殊的部分,就像<variable_name>。这样做,会传递一个关键字变量到你的方法中。你还可以指定一个转换器规则用于转换数据类型,就像<converter:variable_name>,当然这不是必须的。这里有一些简单的示例:

@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return 'User %s' % username


@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

        下面列出合法的转换器:

string接受任何不带斜杠的文本(默认)
int接受整型数值
float类似于int,但是只接受浮点数类型的值
path类似于string,但是能接受带斜杠的文本
any匹配所提供的的项目之一(matches one of the items provided)
uuid接受UUID的字符串

4.2 独一无二的URL网址 / 重定向的行为

        Flask的URL规则是继承于Werkzeug的路由模块。该模块背后的理念是根据Apache和早期HTTP服务器的先例,确保漂亮和独特的URL。

        揣上这两个规则进入下面的示例:

@app.route('/projects/')
def projects():
    return 'The project page'


@app.route('/about')
def about():
    return 'The about page'

        乍一看之下,这两个路由很像,但他们不同点在于他们的URL定义中是否使用了尾斜杠。在第一个示例中,projects端点的标准URL地址携带有一个尾斜杠。从这个意义上来说,他类似于文件系统的文件夹。访问projects端点但是不携带尾斜杠的话,会导致Flask重定向到带有尾斜杠的标准URL地址。

        在第二个示例中,URL是没有尾斜杠的,就像类UNIX系统的文件路径名一样。访问这个不带尾斜杠的URL会产生一个404“Not Found”的错误。

        这种行为允许即使尾斜杠被省略掉的相对URL地址也能继续工作,这与Apache和其他服务器的工作方式是一致的。因此,URL是需要独一无二的,这样做才能使搜索引擎避免两次索引到同一个页面上。

4.3 URL的建立

        为了创建一个URL到一个指定的方法,我们可以使用url_for()方法。url_for方法的第一个参数接受指定方法的名称,还可以带上一些关键字参数,每个关键字参数都对应到URL的可变部分。未知变量部分被追加到URL作为查询参数。

        为什么要使用URL的换向方法——url_for()来构建URL,而不是将它硬编码在模板中?有五个理由:

        1. 换向方法通常比硬编码的URL更具有描述性。

        2. 你可以一次性地更改URL,而不必将散落在各处的URL逐个修改。

        3. URL建立时将会为你透明地处理特殊字符和Unicode数据的转义,这样你就不必处理它们了。

        4. 这种方式生成的路径总是绝对的,避免了浏览器中相对路径引起的未知行为。

        5. 如果你的应用程序被放置在了URL根之外,比如,在“/myapplication”中而不是“/”中,那么url_for()将会正确地处理这个问题。

        举个栗子,这里我们使用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

4.3 HTTP的方法

        HTTP知道访问URL的不同方法。默认情况下,一个路由只能回复GET请求,但可以通过为route()修饰符提供methods参数来改变这一点。这里有些示例:

from flask import request


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

        如果GET请求是存在的,那么HEAD请求是会被自动添加的。你不必处理这个问题。它还将确保HEAD请求被处理为HTTP RFC(描述HTTP协议的文档)的要求,因此你可以完全忽略HTTP规范的这一部分。同样的,对于Flask0.6版本,也会为你自动实现OPTIONS请求。

        你对于HTTP的方法一无所知?没关系,这里有一些关于HTTP方法的简介以及它们的功能:

        HTTP方法(通常也被称为“the verb”)告诉服务端,客户端在请求页面上希望做什么。下面列出常用的方法:

        GET

                浏览器会通知服务器只获取存储在该页面上的信息并将其发送出去。这可能是最常用的方法了。

        HEAD

                浏览器通知服务器获取信息,但它仅仅对headers中的信息感兴趣,而对页面的内容并不感冒。应用程序处理这个的方式,就好比接收了一个GET请求,但是却没有交付给实际的内容。在Flask中你不必处理这些东西,在Werkzeug库中已经为你处理了所有这些问题。

        POST

                浏览器告诉服务器,它想要发布一些新信息到URL,并且服务器需要确认这些数据已经有且仅有一次被存储。这就是HTML表单常用的传输数据到服务器的方式。

        PUT

                与POST类似,但是服务器在多次覆盖旧数据时可能多次触发存储过程。可能你会发问为什么要这么用,这里有一些不错的理由让我们这样做。考虑一下在传输过程中网络连接断开了的情形:在这种情形下,服务器与浏览器之间的系统可以在不破坏其他数据的情况下第二次安全地接收到同样的请求。而POST请求是不可能做到这点的,因为它只能被触发一次。

        DELETE

                删除指定位置的信息。

        OPTIONS

                为客户端提供一个快捷方法来确定在这个URL中支持哪些方法。从Flask0.6版本开始,这是自动实现的。

        有趣的是,在HTML4和HTML1中,提交表单到服务器的方法是GET和POST。但是在JavaScript和未来的HTML标准中,你可以使用其他方法。另外,HTTP变得越来越受欢迎,浏览器不再是使用HTTP的唯一客户端了。例如,很多版本控制系统都在使用HTTP。


5 静态文件

        动态Web应用程序也会使用到静态文件,通常使用的是CSS和JavaScript文件。理想情况下,你的Web服务端是需要由你进行配置来支持静态文件,在开发Flask程序的过程中也可以实现静态文件的支持。你需要在你的包中创建一个叫做static的文件夹,或者在你的模块旁边创建一个static文件夹,然后在应用程序中就可以使用在static文件夹下的静态文件了。

        为了给静态文件生成URL,我们需要使用特殊的端点名“static”:

url_for('static', filename='style.css')

        在文件系统中此文件存储在static/style.css。


6. 渲染模板

        使用Python生成HTML表单是很苦逼的事,因为你需要自己做HTML的转义功能才能保证应用程序的安全性。正因如此,Flask推出了Jinja2模板引擎来做这些事。

        为了渲染一个模板,你可以使用render_template()方法。你所需要做的仅仅是提供模板的名称和你想要传递给模板引擎的关键字变量。这里有一些示例演示了如何渲染一个模板:

from flask import Flask, render_template


app = Flask(__name__)


@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

        Flask会在templates目录下查找模板。因此如果你的应用程序是一个模块,那么这个文件夹是需要紧邻这个模块的;如果你的应用程序是一个包,那么这个文件夹是包含在包内的:

        示例1 一个模块:

/application.py
/templates
    /hello.html

        示例2 一个包:

/application.py
    /__init__.py
    /templates
        /hello.html

        对于模板,你可以使用Jinja2模板的全部功能。你可以前往Jinja2模板文档获取更多的信息。

        这里提供一个模板示例:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

        在模板内部,你也可以通过调用get_flashed_messages()方法来访问requestsessiong对象。

        注意:不确定g对象是什么?它可以由你自己决定,根据具体需求来存储某些数据。你可以查询g对象的文档,还可以在《在Flask下使用SQLite》一文中找到答案。

        当继承能被使用的时候,模板就显得格外有用了。如果你想要知道它是怎么运作的,请前往模板继承模式中查找答案。基本上,模板继承使得每个页面保持某些元素成为了可能(比如页眉、导航、页脚等)。

        自动转义功能在启动的情况下,如果文件名称包含了HTML,那么这个文件就会被自动转义。如果你觉得某个变量是可以信任的,并且你知道它将是安全的HTML(例如,它来自一个将wiki标记转换为HTML的木块),你可以通过使用标记类(Markup)或者在模块中使用安全过滤器来标记它是安全的。你可以前往Jinja2的文档获取更多示例。

        下面是标记类(Markup)如何工作的基本介绍:

>>> from flask import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup(u'<strong>Hello <blink>hacker</blink>!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup(u'<blink>hacker</blink>')
>>> Markup('<em>Marked up</em> » HTML').striptags()
u'Marked up \xbb HTML'

        从版本0.5开始的变化:自动转义不再为所有模板都开启。只有以下模板才会触发自动转义:.html,.htm,.xml,.xhtml。从一个字符串加载的模板会关闭自动转义功能。


7. 访问请求数据

        对于Web应用程序来说,响应客户端发送过来的数据是非常重要的。在Flask中,这个信息是在全局变量request中提供的。如果你对Python有一定了解,你一定会惊奇,这个对象居然是全局的,以及Flask要怎么管理这个才依旧能实现线程安全的?这些问题的答案就是本地上下文。

7.1 本地上下文

        皮一下很开森~

        如果你希望明白本地上下文是怎么工作的,以及怎样才能实现一个本地上下文的测试,你就继续阅读本章节,不然就滚蛋到下一章节。

        在Flask中某些对象称为全局变量,但又不是我们通常意义的那种。这些对象实际上是另外一些特定上下文对象的代理。是不是很绕口?但这实际上是很容易理解的。

        设想这里说的上下文是处理线程。当一个请求进来时,Web服务决定生成一个新的线程(或者其他什么鬼,基础对象有能力处理除了线程以外的并发系统)。当Flask启动其内部请求处理时,它会发现当前线程是活跃的上下文,并将当前的应用程序和WSDI环境绑定到这个上下文(线程)。它以一种智能的方式实现这一点,因此一个应用程序可以在不被中断的情况下调用另一个应用程序。

        那么这些对你来说意味着什么呢?基本上,你可以完全忽略这个例子,除非你要做的是单元测试。你会注意到,依赖于请求对象的代码会突然中断,因为这里不存在请求对象。解决方法是你自己创建一个请求对象,并且将这个请求对象绑定到上下文当中。单元测试最简单的方法是使用test_request_context()这个上下文管理器。结合with语句,它将绑定一个测试请求,这样你就可以与之交互。示例如下:

from flask import Flask, request


app = Flask(__name__)


with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert(request.path == '/hello')
    assert(request.method == 'POST')

        另外一个方法是传递整个WSGI环境给request_context()方法:

from flask import Flask, request


app = Flask(__name__)


with app.request_context(environ):
    assert(request.method == 'POST')

7.2 请求对象

        请求对象在API部分(请跳转request)中有详细讲解,这里不再赘述。以下是一些最常见的操作的概述。

        首先,你需要从flask模块导入request:

from flask import request

        当前的请求方法是通过使用method属性来获取的。为了访问表单数据(数据是通过POST或者PUT请求传输的),你可以使用form属性。示例如下:

@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_templates('login.html', error=error)

        如果form属性中并不存在指定的关键字会发生什么事?答:会抛出一个KeyError的异常。你可以捕获这个KeyError的异常,但你不必这么做,因为这里会跳转到一个HTTP 400 Bad Request的错误页面。因此很多场景下你都不必处理这个问题。

        为了访问提交到URL中的参数(?key=value),你可以使用args属性:

search_word = request.args.get('key', '')

        访问URL的参数时,推荐使用get或者捕获KeyError异常,因为用户可能更改这个URL,那么就会导致出现HTTP 400 Bad Request页面的出现,这对用户来说并不友好。

        想要查看request对象的所有方法和属性,请前往request文档。

7.3 文件上传

        在Flask中你可以很轻松地完成上传文件。你只需要保证再你的HTML表单中不要忘了设置“enctype=multipart/form-data”属性,否则浏览器不会传输文件。

        上传的文件被存储在内存中,或是存储在文件系统的某个临时路径下。在request对象中你可以在files属性中访问到这些文件。所有上传的文件都存储在这个字典中。它的行为就好像是标准Python库中的file对象,并且它还有一个save()方法,用于允许你存储文件到文件系统或者服务器上。示例如下:

from flask import Flask, request


app = Flask(__name__)


@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

        如果你想要知道在该文件上传到你的程序之前它是被如何命名的,那么你可以访问filename属性。然而请记住,这个值是可以被伪造的,因此永远不要相信这个值。如果你想要使用客户端的文件名存储到服务端上,你需要使用Werkzeug库提供的secure_filename()方法来传递这个值:

from flask import Flask, request


app = Flask(__name__)


@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/' + secure_filename(f.filename))
    ...

        想要查看更多更棒的示例,请前往上传文件模式。

7.4 Cookies

        为了访问Cookies,你可以使用cookies属性。设置cookies可以使用响应对象的set_cookie方法。请求对象的cookies属性是一个字典,其包含了客户端传输的所有cookie。如果你想要使用sessions,那么就不要直接使用cookies,而是使用Flask中的Sessions(见后文),这样可以在cookies的顶层增加一些安全性。

        读取cookies:

from flask import Flask, request


app = Flask(__name__)


@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 Flask, request


app = Flask(__name__)


@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

        需要注意的是,cookies在设置的时候需要设置到响应对象(response objects)上。通常你只是从视图方法中返回字符串,因此Flask会将它们转换到响应对象内。如果你希望显示地这样做,你可以使用make_response()方法去修改它。

        有时候你可能希望在响应对象不存在的时候设置一个cookie,可以使用延迟请求回调模式来实现。

        你也可以查阅后面的关于响应章节。


8. 重定向与错误

        为了重定向到另一个端点,可以使用redirect()方法;为了用错误代号提前终止一个请求,可以使用abort()方法:

from flask import Flask, redirect, url_for, abort


app = Flask(__name__)


@app.route('/')
def index():
    return redirect(url_for('login'))


@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

        这是一个毫无意义的示例,因为用户将被重定向到一个无法访问的页面(401意味着访问被拒绝),但这个示例为我们呈现了redirect和abort是如何工作的。

        默认情况下,每个错误代码都会显示在一个黑白错误页面上。如果你想要自定义这个错误页面,你可以使用errorhandler()修饰符:

from flask import render_template


app = Flask(__name__)


@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

        需要注意的是,404是在render_template()方法调用后,不要遗漏了。这样会告诉Flask,这个页面的状态码是404,意味着没有找到页面。默认情况下,200的意思是:一切运行正常。

        请前往错误处理查阅更多细节。


9. 关于响应

        从视图方法中返回的值会自动地转换为一个响应对象。如果返回值是一个字符串,它转换的响应对象的数据包括,响应对象的主体即为该字符串,一个200 OK的状态码(status code),一个text/html的类型。Flask将返回值转换为响应对象的逻辑如下:

        1. 如果返回的是一个正确类型的响应对象,则直接从视图返回。

        2. 如果返回一个字符串,创建的响应对象会包含这个字符串,其他参数则使用默认值。

        3. 如果返回一个元组,那么元组中的元素可以提供额外的信息。这样的元组必须在表单中(response,status,headers),或者至少有一个项目(response,headers)存在于元组中。status的值会覆盖状态码(status code),而headers必须是一个list或者一个dictionary用于附加到头(header)的值中。

        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


10. 会话(Sessions)

        除了请求对象以外,还有另一个叫做session的对象,它允许你将特定于用户的信息从一个请求存储到另一个请求。这是在cookies之上实现的,并且以加密的方式标记了cookies。这意味着用户可以查看cookie的内容,但没有办法修改它,除非用户知道标记的密钥。

        为了使用sessions,我们需要设置一个密钥。这里显示sessions是如何使用的:

from flask import Flask, session, redirect, url_for, escape, request


app = Flask(__name__)


@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():
    # remote the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))


# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

        在这里的escape()方法用于,在没有使用模板引擎的情况下,将字符串进行转义。

        怎样生成一个好一点的密钥:

        使用随机方法的问题在于很难判定这个是不是真的随机生成。理论上一个密钥应当是越随机越合适。操作系统可以根据加密随机生成器来生成一些随机的东西。使用下面的命令可以为Flask.secret_key(或者SECRET_KEY)快速生成一个值:

$ python -c 'import os; print(os.urandom(16))'
b'_5#y2L"F4Q8z\n\xec]/'

        这里关于sessions是基于cookie的问题再说明一下:Flask会获取你推送到session对象的值并且将这些值序列化存储到cookie中。如果你发现某些值并没有在请求期间持久存储,而cookies也是开启状态,并且你没有得到一个明确的错误信息,那么你需要检查你的页面响应的cookie大小,再看看浏览器的cookie大小是不是小于这个值。

        这些都是基于客户端的会话,如果你想要处理服务端的会话,Flask有一些扩展是能够支持你这个想法的(这里不做介绍)。


11. Message Flashing

        (没有什么合适的词来翻译这个标题,索性也就不翻译了。)

        好的应用程序和用户接口都是拥有消息反馈的。如果用户没有得到足够的反馈信息,那么他们最终可能会嫌弃这个应用程序。Flask提供了一个非常简单的方式去为用户提供消息反馈,这个方法就是flashing系统。flashing系统在请求结束时记录一条消息,并能在下一个(并且只有下一个)请求中访问之前那个请求的消息。这种方式通常与布局模板相结合,以用来输出消息。

        为了flash一个消息,可以使用flash()方法。为了能获取到这个消息,你可以使用get_flashed_messages()方法,但是请注意,这个方法只能在模板中使用。请前往Message Flashing获取更多的示例。


12. 记录日志

        这个功能是在0.3版本开始新增的。

        有时候你可能会遇到这种情况:你认为处理数据的方式是正确的,但实际上得到的却不是你期望的结果。举例来说,你可能正准备从客户端想服务器发送一个HTTP请求,但是却得到一个明显的错误结果,这可能是因为用户篡改了数据,也可能是客户端的代码本身就有缺陷。大多数时候可能你会收到一个400 Bad Request的回复,但有时候可能不会有这个错误信息并且程序还能继续工作。

        你可能想记录一下到底发生了什么诡异的事情。所以日志记录器应运而生。Flask0.3开始,日志记录器已经预置在系统中,你可以随时使用。

        这里有一些日志记录器的示例:

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

        附加的日志记录器是一个标准的日志记录器,你可以前往Python的官方网站logging documentation获取更多的信息。

        你也可以阅读以下有关应用程序错误的文章。


13. 连接WSDI中间件

        如果你想要增加一个WSGI中间件,你可以包装内部WSGI应用程序。举个栗子,如果你希望使用Werkzeug包中的某一个中间件来处理lighttpd的错误,你可以这样玩:

from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)


14. 使用Flask的扩展

        扩展就是可以帮助你完成常见任务的包。举个栗子,Flask-SQLAlchemy可以让你在Flask环境下很轻易地使用SQLAlchemy的所有功能。

        想要知道更多的Flask扩展,请前往Flask Extensions


15. 开发一个Web服务

        准备好创建一个新的Flask app了吗?请前往Deployment Options

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值