Flask学习之路

本文介绍了Flask,一个轻量级的Python Web框架。详细讲解了Flask的准备工作、运行及调试模式、路由、静态文件及渲染模板、接收请求数据等方面,包括如何创建应用、配置调试模式、处理动态URL、渲染模板以及接收表单和文件上传数据。通过对Flask的学习,读者可以快速掌握构建Web应用的基础知识。
摘要由CSDN通过智能技术生成

Flask 是一个轻量级的 Web 应用框架, 使用 Python 编写。
基于 Werkzeug WSGI工具箱和 Jinja2模板引擎。使用 BSD 授权。
Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。
Flask没有默认使用的数据库、窗体验证工具。然而,Flask保留了扩增的弹性,可以用 Flask-extension 加入这些功能:ORM、窗体验证工具、文件上传、各种开放式身份验证技术。

Werkzeug不是一个web服务器,也不是一个web框架,而是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等。

准备工作

  1. 新建python虚拟环境, 进入venv
  2. 安装Flask
	pip install flask

一、Flask运行及调试模式

一个最小的应用看起来像这样:
建立hello.py文件。

from flask import Flask
app = Flask(__name__)

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

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

然后用 Python 解释器运行它。

$ python3 hello.py
 * Running on http://127.0.0.1:5000/

现在使用浏览器浏览http://127.0.0.1:5000/,你会看到hello world问候。

那么这段代码做了什么?

  • 首先导入了类 Flask 。这个类的实例化将会是我们的 WSGI 应用。第一个参数是应用模块的名称。 如果你使用的是单一的模块(就如本例),第一个参数应该使用 _name_。因为如果它以单独应用启动或作为模块导入, 名称将会不同 ( _main_ 对应于实际导入的名称)。获取更多的信息,请阅读 Flask 的文档。
  • 接着,我们创建一个该类的实例。我们传递给它模块或包的名称。这样 Flask 才会知道去哪里寻找模板、静态文件等等。
  • 我们使用装饰器route()告诉 Flask 哪个URL才能触发我们的函数。
  • 定义一个函数,该函数名也是用来给特定函数生成 URLs,并且返回我们想要显示在浏览器上的信息。
  • 最后我们用函数run()启动本地服务器来运行我们的应用。
  • 请按Ctrl+c来停止服务器。

外部可见服务器

当你运行服务器,你会注意到它只能从你自己的计算机上访问,网络中其它任何的地方都不能访问。 这是因为默认情况,调试模式,只有应用中的一个用户可以执行你计算机上的任意 Python 代码。
如果你关闭 debug 或者信任你所在网络上的用户,你可以让你的服务器对外可用,只要简单地改变脚本中方法run()的调用,如下这样:

	app.run(host='0.0.0.0')

这让你的操作系统去监听所有公开的 IP。

调试模式

run()方法是十分适用于启动一个本地开发服务器,但是你需要在修改代码后手动重启服务器。 这样做并不好,Flask 能做得更好。如果启用了调试支持,在代码修改的时候服务器能够自动加载, 并且如果发生错误,它会提供一个有用的调试器。

有两种方式开启调式模式。一种是在应用对象上设置标志位:

app.debug = True

或者作为run的一个参数传入:

app.run(debug=True)

两种方法效果是一样的。

二、路由

route装饰器是用于把一个函数绑定到一个 URL 上。
但是不仅如此!你可以动态地构造 URL 的特定部分,也可以在一个函数上附加多个规则。

  1. 变量规则
    为了给 URL 增加变量的部分,需要把一些特定的字段标记成<variable_name>。这些特定的字段将作为参数传入到函数中。当然也可以指定一个可选的转换器通过规则converter:variable_name将变量值转换为特定的数据类型。例子:
@app.route('/user/<username>')
def show_user_profile(username):
    # 显示用户的名称
    return 'User %s' % username

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # 显示提交整型的用户"id"的结果,注意"int"是将输入的字符串形式转换为整型数据
    return 'Post %d' % post_id
  1. 唯一 URLs / 重定向行为:
    Flask 的 URL 规则是基于 Werkzeug 的 routing 模块。 该模块背后的想法是基于 Apache 和早期的 HTTP 服务器定下先例确保美丽和唯一的 URL。

以这两个规则为例:

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

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

虽然它们看起来确实相似,但它们结尾斜线的使用在 URL 定义中不同。
第一种情况中,规范的 URL 指向 projects 尾端有一个斜线/。 这种感觉很像在文件系统中的文件夹。访问一个结尾不带斜线的 URL 会被 Flask 重定向到带斜线的规范URL去。
第二种情况的 URL 结尾不带斜线,类似 UNIX-like 系统下的文件的路径名。此时如果访问结尾带斜线的 URL 会产生一个404 “Not Found”错误。
当用户访问页面时忘记结尾斜线时,这个行为允许关联的 URL 继续工作, 并且与 Apache 和其它的服务器的行为一致, 反之则不行,因此斜线只可少写不可多写;另外,URL 会保持唯一,有助于避免搜索引擎索引同一个页面两次。

  1. 构建 URL
    如果它可以匹配 URL ,那么 Flask 能够生成它们吗?当然 Flask 能够做到。你可以使用函数url_for()来针对一个特定的函数构建一个 URL 。它能够接受函数名作为第一参数,以及一些关键字参数, 每一个关键字参数对应于 URL 规则的变量部分。未知变量部分被插入到 URL 中作为查询参数。
$ python3
>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> 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=%2F
/user/John%20Doe

这里使用了test_request_context()方法,这个方法告诉 Flask 表现得像是在处理一个请求,即使我们正在通过 Python 的 shell 交互。

为什么你要构建 URLs 而不是在模版中硬编码?这里有三个好的理由:

  • 反向构建通常比硬编码更具备描述性。更重要的是,它允许你一次性修改 URL, 而不是到处找 URL 修改。
  • 构建 URL 能够显式地处理特殊字符和Unicode转义,因此你不必去处理这些。
  • 如果你的应用不在 URL 根目录下(比如,在 /myapplication 而不在 /),url_for()将会适当地替你处理好。

三、静态文件及渲染模版

  1. 静态文件
    动态的 web 应用同样需要静态文件。CSS和JavaScript文件通常来源于此。理想情况下, web 服务器已经配置好为它们服务,在开发过程中 Flask 就能够做到。 只要在你的包中或模块旁边创建一个名为static 的文件夹,在应用中使用/static即可访问。
<link rel="stylesheet" type="text/css" href="/static/style.css"/>
  1. 渲染模板
    在 Python 中生成 HTML 并不好玩,实际上是相当繁琐的,因为必须自行做好HTML转义以保持应用程序的安全。 由于这个原因,Flask 自动配置好 Jinja2 模版。
    可以使用方法render_template()来渲染模版。所有你需要做的就是提供模版的名称以及你想要作为关键字参数传入模板的变量。这里有个渲染模版的简单例子, 修改hello.py文件:
from flask import render_template

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

Flask 将会在templates文件夹中寻找模版。因此如果你的应用是个模块,这个文件夹在模块的旁边,如果它是一个包,那么这个文件夹在你的包里面:
然后编写hello.html模板文件:

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

四、接收请求数据

  1. 请求对象
    首先你需要从 flask 模块中导入request
    当前请求的方法可以用method属性来访问。你可以用form属性来访问表单数据 (数据在 POST 或者PUT中传输)。
@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'
    # 当请求形式为“GET”或者认证失败则执行以下代码
    return render_template('login.html', error=error)
  • 如果在form属性中不存在上述键值会发生些什么?在这种情况下会触发一个特别的KeyError。你可以像捕获标准的KeyError一样来捕获它,如果你不这样去做,会显示一个HTTP 400 Bad Request错误页面。所以很多情况下你不需要处理这个问题。
  • 你可以用args属性来接收在URL ( ?key=value )中提交的参数:
searchword = request.args.get('key', '')
  • 推荐使用get来访问 URL 参数或捕获KeyError,因为用户可能会修改 URL, 向他们显示一个400 bad request页面不是用户友好的。
  1. 文件上传
    能够很容易地用 Flask 处理文件上传。只要确保在你的 HTML 表单中不要忘记设置属性enctype=“multipart/form-data”,否则浏览器将不会传送文件。
    上传的文件是存储在内存或者文件系统上一个临时位置。你可以通过请求对象中files属性访问这些文件。每个上传的文件都会存储在这个属性字典里。它表现得像一个标准的 Python file对象,但是它同样具有save()方法,该方法允许你存储文件在服务器的文件系统上。
from flask import request

@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 request
from werkzeug import secure_filename

@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))
    ...
  1. Cookies
    你可以用cookies属性来访问cookie。你能够用响应对象的set_cookie来设置cookie。请求对象中的cookies属性是一个客户端发送所有的cookies的字典。
    如果你要使用会话(sessions),请不要直接使用cookies,相反,请用 Flask 中的会话,Flask 已经在cookies上增加了一些安全细节。

读取 cookies:

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # 注意这里引用cookies字典的键值对是使用cookies.get(key)
    # 而不是cookies[key],这是防止该字典不存在时报错"keyerror"

存储 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。利用延迟请求回调模式使得这种情况成为可能。

flask 的请求,如果想在没有请求的情况下获取上下文,可以使用test_request_context()或者request_context(),从request对象的form中可以获取表单的数据,args中可以获取 URL 中的参数,files可以获取上传的文件,cookies可以操作cookie。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值