use*_*707 8 python flask xhtml2pdf
以下代码给出错误:
Traceback (most recent call last):
File "pdf.py", line 14, in <module>
create_pdf(render_template('templates.htm'))
File "/usr/local/lib/python2.7/dist-packages/flask/templating.py", line 123, in render_template
ctx.app.update_template_context(context)
AttributeError: 'NoneType' object has no attribute 'app'
Run Code Online (Sandbox Code Playgroud)
码:
from xhtml2pdf import pisa
from StringIO import StringIO
from flask import render_template,Flask
app=Flask(__name__)
app.debug=True
@app.route("/")
def create_pdf(pdf_data):
filename= "file.pdf"
pdf=pisa.CreatePDF( StringIO(pdf_data),file(filename, "wb"))
if __name__ == "__main__":
create_pdf(render_template('templates.htm'))
Run Code Online (Sandbox Code Playgroud)
chu*_*ash 17
Martin的回答很好地解释了为什么会出现这种错误.
接受的答案解决了所提出的问题,但肯定不是唯一的方法.就我而言,我有更喜欢的东西:
import threading
from flask import Flask, render_template
app = Flask("myapp")
app.route('/')
def get_thing(thing_id):
thing = cache.get(thing_id)
if thing is None:
# Handle cache miss...
elif is_old(thing):
# We'll serve the stale content but let's
# update the cache in a background thread
t = threading.Thread(
target=get_thing_from_datastore_render_and_cache_it,
args=(thing_id,)
)
t.start()
return thing
def get_thing_from_datastore_render_and_cache_it(thing_id):
thing = datastore.get(thing_id)
cache.set(render_template(thing))
Run Code Online (Sandbox Code Playgroud)
但是当get_thing_from_datastore_render_and_cache_it在Flask请求周期之外的后台线程中运行时,我收到上面显示的错误,因为该线程无法访问请求上下文.
发生错误是因为Flask提供了一个开发人员快捷方式,允许自动访问模板中的请求变量 - 换句话说,它是由Flask关于如何包装Jinja2的功能而不是Jinja2本身的决定引起的.我解决这个问题的方法就是直接使用Jinja2的渲染:
import jinja2
def render_without_request(template_name, **template_vars):
"""
Usage is the same as flask.render_template:
render_without_request('my_template.html', var1='foo', var2='bar')
"""
env = jinja2.Environment(
loader=jinja2.PackageLoader('name.ofmy.package','templates')
)
template = env.get_template(template_name)
return template.render(**template_vars)
Run Code Online (Sandbox Code Playgroud)
该函数假定您的Flask应用程序具有传统模板子文件夹.具体来说,这里的项目结构将是
.
??? name/
??? ofmy/
| ??? package/
| | ??? __init__.py <--- Where your Flask application object is defined
| | ??? templates/
| | ??? my_template.html
| ??? __init__.py
??? __init__.py
Run Code Online (Sandbox Code Playgroud)
如果你有一个子目录结构templates/,你只需要传递模板文件夹根目录的相对路径,就像使用Flask时一样render_template.
Mar*_*ard 12
Flask做了很多"魔术",所以你不必担心路由或解析请求.当Flask应用程序收到请求时,它会在将逻辑委托给您的视图函数之前创建一个"上下文"对象.
在您的代码中,您render_template无需通过Flask即可直接调用,因此不会创建上下文.render_template试图app通过这个context(ctx)来到你的应用程序(),这就是None错误:
AttributeError: 'NoneType' object has no attribute 'app'
Run Code Online (Sandbox Code Playgroud)
现在这不是你的代码唯一的问题.查看函数(在装饰器中注册@app.route(...))不应直接调用.@ rajpy的答案为您提供了如何使用它们的一个很好的例子.
尝试从Celery任务渲染模板时,我遇到了同样的问题。
事实证明,最简单的解决方案是手动推送所需的上下文:
with app.app_context():
# Code calling render_template goes here
Run Code Online (Sandbox Code Playgroud)
从代码中,我可以看到您要允许用户下载pdf。
from xhtml2pdf import pisa
from StringIO import StringIO
from flask import render_template,Flask, Response
app=Flask(__name__)
app.debug=True
@app.route("/")
def create_pdf(pdf_data):
filename= "file.pdf"
pdf=pisa.CreatePDF( StringIO(pdf_data),file(filename, "wb"))
return Response(pdf, mimetype='application/octet-stream',
headers={"Content-Disposition": "attachment;filename=%s" % filename})
if __name__ == "__main__":
app.run()
Run Code Online (Sandbox Code Playgroud)
现在开始 python aboveprogram.py
去 http://localhost:5000
浏览器提示下载PDF。希望能帮助到你..
| 归档时间: |
|
| 查看次数: |
13641 次 |
| 最近记录: |