flask的访问

本文介绍了Flask框架中route装饰器的深入解析,包括URL变量规则、重定向与错误处理、请求与响应、会话管理、日志记录、WSGI中间件、文件上传、静态文件以及各种功能如session、模板渲染和异常处理的应用。
摘要由CSDN通过智能技术生成

route装饰器解析
变量名规则:RESTful风格的URL
重定向和错误页处理
请求
响应
session
日志
WSGI中间件
文件上传
静态文件

route路由解析

route函数的实现如下:

    def route(self, rule: str, **options: t.Any) -> t.Callable:
        def decorator(f: t.Callable) -> t.Callable:
            endpoint = options.pop("endpoint", None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f

        return decorator

可以发现route()主要作用是装饰了一个add_url_rule()的函数
而add_url_rule()才是设置路由的函数
如下代码证明:

from flask import Flask

app = Flask(__name__)


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

def index():
    return 'index'


app.add_url_rule('/index', view_func=index)# view_func为视图函数,路由必填

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

run后在浏览器测试http://127.0.0.1:5000/index可以发现 确实!

变量名规则

from flask import Flask

import settings

app = Flask(__name__)
app.config.from_object(settings)

@app.route('/hello/<who>')
def hello_world(who):
    return 'Hello World!'+who


@app.route('/index/<string:key>')
def index(key):
    return 'index'+key


app.add_url_rule('/index', view_func=index)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

类似restful风格的路由
参数规则中,变量名默认是string类型
路由格式:<variable_name><converter:variable_name>

变量名类型有如下:
string:(缺省值) 接受任何不包含斜杠的文本
int:接受正整数
float:接受正浮点数
path:类似 string ,但可以包含斜杠
uuid:接受 UUID 字符串

视图函数返回值

只可以返回如下类型变量:

string
dict
tuple
Response instance
WSGI callable

重定向和错误

url构建

url_for()把函数名称作为第一个 参数。它可以接受任意个关键字参数,每个关键字参数对应 URL 中的变量。未知变量 将添加到 URL 中作为查询参数。
我的理解是:第一个参数是视图函数的函数名,第二个参数是(路由变量名=value)的形式

from flask import 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 f'{username}\'s profile'

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

重定向到错误页面示例

使用 redirect() 函数可以重定向。使用 abort() 可以 更早退出请求,并返回错误代码
每种出错代码都会对应显示一个黑白的出错页面。使用 errorhandler() 装饰器可以定制出错页面
render_template() 方法可以渲染模板,您只要提供模板名称和需要作为参数传递给模板的变量就行。例如,return render_template('hello.html', name=name),此时html页面可以接受name变量,展示示例:

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}
# settings.py
DEBUG=True
<!-- not_login.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>未登录</title>
</head>
<body>
    <h1>未登录</h1>
</body>
</html>
# app.py
import logging

from flask import Flask, redirect, url_for, abort, render_template

import settings

app = Flask(__name__)
app.config.from_object(settings)


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


@app.route('/login')
def login():
    abort(403)# 


@app.errorhandler(403)# 错误页路由
def not_login(error):
    logging.error(error)
    return render_template('not_login.html'), 403# render_template() 后面的 403是响应状态码 。缺省情况下 200 表示:一切正常。


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

访问网址:http://127.0.0.1:5000将看到“未登录”的h1字体
render_template() 方法可以渲染模板,您只要提供模板名称和需要 作为参数传递给模板的变量就行了。

请求

@app.route("/")
def index():
    logging.error("method:" + request.method)
    if request.method == "GET":
        form = request.args if request.args else None
    elif request.method == "POST":
        form = request.form if request.form else None# 当 form 属性中不存在这个键时会发生什么?会引发一个 KeyError
    if form:
        logging.error("form:" + form)

url后面有参数时,可以通过args.get获取,比如searchword = request.args.get('key', '')
推荐使用 get 或通过捕捉 KeyError 来访问 URL 参数。

扩展cookie

username = request.cookies.get('username')

可以使用响应 对象 的 set_cookie 方法来设置 cookies 。(响应对象在下面会介绍到,可以看完以下内容再回顾cookie,也可以跳过cookie,resp.set_cookie('username', 'the username')
请求对象的 cookies 属性是一个包含了客户端传输的所有 cookies 的字典。可以通过username = request.cookies.get('username')调用

响应

视图函数的返回值会自动转换为一个响应对象。那么如果不是响应对象则将返回对象转换为响应对象
转换规则:

  • 如果视图返回的是一个响应对象,那么就直接返回它。
  • 如果返回的是一个字符串,那么根据这个字符串和缺省参数生成一个包含作为响应体的字符串、一个 200 OK 出错代码 和一个 text/html 类型的响应对象。
  • 如果返回的是一个字典,那么调用 jsonify 创建一个响应对象。
  • 如果返回的是一个元组,那么元组中的项目可以提供额外的信息。元组中必须至少 包含一个项,且项应当由 (response, status) 、 (response, headers) 或者 (response, status, headers) 组成。 status 的值会重载状态代码, headers 是一个由额外头部值组成的列表 或字典。
  • 如果以上都不是,那么 Flask 会假定返回值是一个有效的 WSGI 应用并把它转换为 一个响应对象。
# jsonify使用样例
jsonify([user.to_json() for user in users])

如果想要在视图内部掌控响应对象的结果。可以使用 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更安全

session 对象相当于用密钥签名加密的 cookie ,即用户可以查看您的 cookie ,但是如果没有密钥就无法修改它。
那么如何生成密钥?可以快捷的为 Flask.secret_key ( 或者 SECRET_KEY )生成值:

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

那么会话可以进行如下使用:

from flask import session

# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    if 'username' in session:
        return f'Logged in as {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'))

日志

Flask 0.3 后配置 了一个日志工具logger

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

WSGI中间件

要在应用中添加一个 WSGI 中间件,那么可以用应用的 wsgi_app 属性 来包装。例如,假设需要在 Nginx 后面使用 ProxyFix 中间件,那么可以这样做:

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

用 app.wsgi_app 来包装,而不用 app 包装,意味着 app 仍旧指向您 的 Flask 应用,而不是指向中间件。这样可以继续直接使用和配置 app 。

文件上传

不要忘记在您的 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 werkzeug.utils import secure_filename

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

静态文件

静态文件,一般是 CSS 和 JavaScript 文件。只要在包或模块旁边创建一个名为 static 的文件夹就行了。 静态文件位于应用的 /static 中。例如:url_for('static', filename='style.css')在文件系统中的位置应该是 static/style.css

其他

此类为扩展知识,自行了解

flash()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值