AttributeError: object 'NoneType' does not have attribute 'app'

The following is the error code:

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' 

code:

 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')) 
+6
source share
3 answers

From the code, I see that you want to allow the user to download 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() 

Now run python aboveprogram.py

Go to http://localhost:5000

The browser offers to download a PDF file. Hope this helps.

+3
source

Flask does a lot of magic, so you don’t have to worry about routing requests or parsing. When a Flask application receives a request, it creates a context object before passing the logic to your view function.

In your code, you call render_template directly without going through Flask, so no context is created. render_template trying to navigate to your application ( app ) through this context ( ctx ) which is None , so the error is:

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

Now this is not the only thing that is wrong with your code. The viewing functions (registered in the @app.route(...) decorator) are not intended to be called directly. @Rajpy's answer gives you a good example of how to use them.

+10
source

Martin's answer gives a good explanation of the reasons for this error.

The accepted answer fixes the problem posed, but this, of course, is not the only way. In my case, I had something more:

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

But when get_thing_from_datastore_render_and_cache_it running in the background thread outside the jar request loop, I got the error shown above because this thread did not have access to the request context.

The error arises because Flask offers a shortcut for developers to automatically access query variables in the template - in other words, this is caused by Flask's decisions on how to wrap Jinja2 and not Jinja2 functionality. My approach to solving this issue was to use Jinja2 directly:

 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) 

This feature assumes that your Flask application has a traditional template subfolder. In particular, the project structure will be here

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

If you have a subdirectory structure in templates/ , you simply pass the relative path from the root of the templates folder in the same way as when using Flask render_template .

+10
source

Source: https://habr.com/ru/post/947708/


All Articles