好的,正如我所提到的,redis 是一个非常酷的后端。当您在 PythonAnywhere 上托管时,实际上有一个名为 redislite 的库,它将使用本地文件而不是实际的 redis 服务器来提供此功能。
它出现在 PythonAnywhere,don't support redis 但do support persistant storage。更好的是,如果你以后搬到有实际redis服务器的主机上,应该是两行修改才能切换。
这背后的概念是:
- 在
/join 路由中,创建一个UUID 用作unique_id 并将其与dict 一起存储在redis 中,然后将unique_id 传递回模板,将其作为链接呈现给用户。
- 在
/pdf路由中,根据URL字符串中的unique_id从redis中获取dict。
- 对于奖励积分,我们可以在 redis 键上设置一个过期时间,因此在
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并设置到期时间。
然后我将键 pdf_link 添加到您的 result dict 并将值设置为 PDF 的 URL,由 flask 的 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)
这会产生一个带有键的 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 链接的人都可以下载它,前提是它尚未过期,因此您可能不应该在未经身份验证的情况下通过此链接传递个人信息。