主页是一个表单,然后当用户单击“计算”时,会根据表单进行计算,并将其存储在字典中,然后传回以填充表格。简要如下:
@app.route('/join', methods=['GET','POST'])
def my_form_post():
---calculations done and variables set---
data_dict = {
"loco_length":l1, "loco_weight":w1, "loco_bweight":b1,
"cargo_length":l2, "cargo_weight":w2, "cargo_bweight":b2,
"total_length":length, "total_weight": weigth, "total_bweight": bweigth,
"bproc":bproc
}
result = {str(key): value for key, value in data_dict.items()}
return jsonify(result=result)
但是后来我创建了第二个函数,我希望通过新路线/pdf 来访问它。 该功能是用“my_form_post”字典中的值填充预定义的 PDF 模板。
第二条路线如下所示,调用函数并需要字典作为参数:
def pdf():
data = write_fillable_pdf(PDF_TEMP_PATH, data_dict)
return send_file(data, mimetype='application/pdf')
如何让字典在函数和路由之间传输或访问?我见过人们提到 session 、json 和全局变量。但我想不通。
感谢您的帮助。
最佳答案
好的,正如我提到的,一个非常酷的后端是 Redis。当您在 PythonAnywhere 上托管时,实际上有一个名为 redislite
的库。它将使用本地文件而不是实际的 Redis 服务器来提供此功能。
出现PythonAnywhere,don't support redis但是do support persistant storage 。更好的是,如果您稍后移动到具有实际 Redis 服务器的主机,则应该只需修改两行即可切换。
其背后的概念是:
- 在
/join
路由,创建一个 UUID 用作unique_id
并将其与 dict 一起存储在 redis 中,然后传递unique_id
返回模板,将其作为链接呈现给用户。 - 在
/pdf
路线,根据unique_id
从redis获取dict在 URL 字符串中。 - 为了获得奖励积分,我们可以在 redis key 上设置过期时间,因此在
n
之后几秒钟后,链接就会消失,用户必须再次点击计算按钮。
首先您需要添加 redislite
符合要求,或pip install redislite
。然后在 Python 文件的顶部包含配置 Redis 连接所需的内容:
from redislite import StrictRedis
import os
REDIS_DB_PATH = os.path.join('/tmp/my_redis.db')
r = StrictRedis(REDIS_DB_PATH, charset='utf-8', decode_responses=True)
您还应该定义到期时间,一个使 redis 键对于这组路由保持唯一的前缀,并导入其他工具:
PDF_EXPIRY = 60*60*24 # 1 day in seconds
PREFIX = 'pdf:' # A prefix for our redis keys
from uuid import uuid4
from flask import url_for
现在下一部分可以工作了,因为您的数据是一个简单的字典,没有嵌套。我在这里使用了模拟版本,然后使用hmset
将其添加到redis中并设置到期时间。
然后我添加 key pdf_link
给您result
dict 并将值设置为由 Flask 构建的 PDF 的 URL url_for
功能:
@app.route('/join')
def my_form_post():
# ---calculations done and variables set---
data_dict = {
"loco_length":3.14, "loco_weight":'str', "loco_bweight":'str',
} # a simplified version of your dictionary
unique_id = uuid4().__str__()
r.hmset(PREFIX + unique_id, data_dict)
r.expire(PREFIX + unique_id, PDF_EXPIRY)
result = {str(key): value for key, value in data_dict.items()}
# This creates a URL back to our PDF route, as a key in result
result['pdf_link'] = url_for('pdf',unique_id = unique_id)
return jsonify(result=result)
这会产生一个带有 key 的 Redis 哈希:pdf:86341e77-f655-46d8-93c4-10e945fc3586
和字段名称/值,如您的 data_dict
的键/值。请参阅 HMSET
redis docs对此的另一个可视化。
现在在前端result.pdf_link
是 PDF 的有效链接,类似于:/pdf/86341e77-f655-46d8-93c4-10e945fc3586
。您可以将其呈现在 <a href=>
中模板上表格旁边的标签。
对该 URL 的请求由下一个路由处理:
@app.route('/pdf/<string:unique_id>')
def pdf(unique_id):
data_dict = r.hgetall(PREFIX + unique_id)
if not data_dict:
return 'Not found or expired', 404
else:
data = write_fillable_pdf(PDF_TEMP_PATH, data_dict)
return send_file(data, mimetype='application/pdf')
我认为这种方法非常干净,因为它避免了为数据构建数据库模型,而这本来是常见的方法。这样,您可以向 data_dict
添加更多值,只要你不嵌套它们,其他什么都不需要改变。
如果您将来想添加对真正的 Redis 服务器的支持,只需将这两行更改为:
from redis import StrictRedis
r = StrictRedis(host='newredisserver', charset='utf-8', decode_responses=True)
因为我们使用的方法在 redis
之间是相同的和redislite
图书馆。
请注意,任何拥有 PDF 链接的人都可以下载该 PDF,前提是该 PDF 尚未过期,因此您可能不应该在未经身份验证的情况下通过此方式传递个人信息。
关于python - Flask:从一个路由/函数访问或传递字典到另一个路由/函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59934360/