2013-06-20 51 views
6

を持っていない:はAttributeError:「NoneType」オブジェクトは、以下のコードはエラーになります何の属性「アプリ」

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' 

コード:、私はあなたがユーザーを許可することを

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')) 

答えて

3

コードからを見ることができます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() 

、ブラウザはPDFをダウンロードするように求められhttp://localhost:5000

python aboveprogram.py

Go]を実行します。 ホープが助けてくれることを願っています。

10

フラスコは「マジック」をたくさんしているので、ルーティングやパーズ要求を心配する必要はありません。 Flaskアプリケーションは要求を受け取ると、ビュー関数にロジックを委譲する前に 'context'オブジェクトを作成します。

コードでは、render_templateをFlaskを経由せずに直接呼び出しているため、コンテキストは作成されません。 render_templateNoneあり、このコンテキスト(ctx)を経由して、アプリケーション(app)、これエラーを取得しようとします。

AttributeError: 'NoneType' object has no attribute 'app' 

さて、これはあなたのコードに問題がある唯一のものではありません。 (デコレータ@app.route(...)で登録されている)ビュー関数は、直接呼び出すことを目的としていません。 @ rajpyの答えは、その使い方の良い例を示しています。

10

の理由については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)) 

をしかしget_thing_from_datastore_render_and_cache_itが、私は上記のようなエラーを得ていたフラスコ要求サイクル外のバックグラウンドスレッドで実行されたとき、そのスレッドは、要求コンテキストへのアクセスを持っていなかったので。

Flaskは、Jinja2自身の機能ではなく、Jinja2の機能を包み込む方法に関するFlaskの決定によって自動的にテンプレート内の要求変数にアクセスするための開発者向けのショートカットを提供するため、エラーが発生します。

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) 

この関数は、あなたのフラスコのアプリは、伝統的なテンプレートサブフォルダを持っていることを前提としています。これを解決するための私のアプローチはJinja2の者が直接レンダリングを使用するだけでした。あなたはtemplates/の下にサブディレクトリ構造を持っている場合は具体的には、ここではプロジェクトの構造が

. 
└── name/ 
    ├── ofmy/ 
    | ├── package/ 
    | | ├── __init__.py <--- Where your Flask application object is defined 
    | | └── templates/ 
    | |  └── my_template.html 
    | └── __init__.py 
    └── __init__.py 

だろう、あなただけのテンプレートのルートからの相対パスを渡すあなたがフラスコのrender_templateを使用する場合と同様に同じフォルダ。

+0

本当にすばらしい説明。私はフラスコの外で仕事をしていたので、私はそれがわからなかった。 –

+0

私は、パッケージの名前をどうやって知っていますか? –

関連する問題