flask app object inside blueprint - python

I know the way to access the flask app obj is using current_app, however, everytime I run that code I get this error: NameError: global name 'current_app' is not defined
What am I doing wrong here?
My folder structure is this:
/project
gateway.py
settings.py
/app
views.py
models.py
I can't access the app object neither from views.py or models.py :S Always get the same error.
The views.py file declares a blueprint wich is registered in the gateway.py file.
I'm using current_app inside a view function inside the views.py file.
Hope you can help me.

Make sure you have
from flask import Flask, current_app
in your code and make sure you call it correctly, because in some context it doesn't get called.

Related

Why is flask rendering the wrong template [duplicate]

I have a Flask app with blueprints. Each blueprint provides some templates. When I try to render the index.html template from the second blueprint, the first blueprint's template is rendered instead. Why is blueprint2 overriding blueprint1's templates? How can I render each blueprint's templates?
app/
__init__.py
blueprint1/
__init__.py
views.py
templates/
index.html
blueprint2/
__init__.py
views.py
templates/
index.html
blueprint2/__init__.py:
from flask import Blueprint
bp1 = Blueprint('bp1', __name__, template_folder='templates', url_prefix='/bp1')
from . import views
blueprint2/views.py:
from flask import render_template
from . import bp1
#bp1.route('/')
def index():
return render_template('index.html')
app/__init__.py:
from flask import Flask
from blueprint1 import bp1
from blueprint2 import bp2
application = Flask(__name__)
application.register_blueprint(bp1)
application.register_blueprint(bp2)
If I change the order the blueprints are registered, then blueprint2's templates override blueprint1's.
application.register_blueprint(bp2)
application.register_blueprint(bp1)
This is working exactly as intended, although not as you expect.
Defining a template folder for a blueprint only adds the folder to the template search path. It does not mean that a call to render_template from a blueprint's view will only check that folder.
Templates are looked up first at the application level, then in the order blueprints were registered. This is so that an extension can provide templates that can be overridden by an application.
The solution is to use separate folders within the template folder for templates related to specific blueprints. It's still possible to override them, but much harder to do so accidentally.
app/
blueprint1/
templates/
blueprint1/
index.html
blueprint2/
templates/
blueprint2/
index.html
Point each blueprint at its templates folder.
bp = Blueprint('bp1', __name__, template_folder='templates')
When rendering, point at the specific template under the templates folder.
render_template('blueprint1/index.html')
See Flask issue #1361 for more discussion.
I vaguely remember having trouble with something like this early on. You haven't posted all of your code, but I have four suggestions based on what you've written. Try the first, test it, and then if it still is not working, try the next ones, but independently test them to see if they work:
First, I cant't see your views.py file, so be sure you're importing the appropriate blueprint in your views.py files:
from . import bp1 # in blueprint1/views.py
from . import bp2 # in blueprint2/views.py
Second, you may need to fix the relative import statements in __init__.py as follows (note the period preceding the subfolders):
from .blueprint1 import blueprint1 as bp1
from .blueprint2 import blueprint2 as bp2
Third, since you're hardcoding the path to your templates in your render_template function, try removing template_folder='templates' from your blueprint definition.
Fourth, it looks like you named the url_prefix for your blueprint as "/bp1" when you registered it. Therefore, if the hard coded link to your file system still does not work:
render_template('blueprint1/index.html')
then also try this and see what happens:
render_template('bp1/index.html')
Again, I can't see your full code, but I hope this helps.

Blueprints in Flask

I am taking over a Flask application that has a user module, but does not have a landing page. The structure of the project is:
|-application.py
|-manage.py
|-settings.py
|-/templates
|----base.html
|----index.html
|----navbar.html
|----/user
|--------views.py
application.py:
from flask import Flask
....
def create_app(**config_overrides):
app = Flask(__name__)
app.config.from_pyfile('settings.py')
app.config.update(config_overrides)
db.init_app(app)
from user.views import user_app
app.register_blueprint(user_app)
return app
user/views.py:
from flask import Blueprint, render_template, request, redirect, session, url_for, abort
...
user_app = Blueprint('user_app', __name__)
#user_app.route('login', methods = ('GET','POST'))
def login():
....
I placed index.html in the templates folder.
Should I place a view.py in the root directory where I would put a route to an index.html?
You can add additional routes anywhere you want.
However, since the package uses a create_app() app factory, you can't register those routes with an #app.route() decorator; the app is not created in a way you can just import.
So yes, creating a views.py module is a good organisational idea, but do create a Blueprint() there too, and register that blueprint in the create_app() function with the Flask() app instance.
In views.py:
from flask import Blueprint
bp = Blueprint('main', __name__)
#main.route('/')
def index():
# produce a landing page
and in create_app() in application.py, add
import views
app.register_blueprint(views.bp)
(I use a convention of using the bp variable name for all my blueprints, and then just importing the module and registering the module.bp attribute).
It's the explicit import and app.register_blueprint() call that ties any of the blueprints used in a Flask project into the final app's routes. Blueprints can share the same prefix, including having no prefix.
One thing to note: here the views module is now a top-level module next to application.py. It'd be better if everything was moved into a package, giving you more freedom over what names you use. All modules in a single package are namespaced, kept separate from other top-level modules such as json and time and flask, so there won't be clashes when you want to use the same name for one of the additional modules in your project.
You'd move everything but manage.py into a subdirectory, with a project-appropriate name, and move application.py to __init__.py. Imports can then use from . import ... to import from the current package, etc.

Why doesn't this cause circular import

I have a flask app.
app.py
app = Flask(__name__)
from views import *
if __name__=="__main__":
app.run()
views.py
from app import app
#app.route('/')
def home():
return "Homepage"
So, here app.py is importing everything form views.py and views need app which is defined in app.py. But still its not causing circular import. Why?
I run this application using:
python app.py
This looks similar to the Larger Applications document which Flask allows you to do when creating apps.
From the docs:
Circular Imports
Every Python programmer hates them, and yet we just added some: circular imports (That’s when two modules depend on each other. In this case views.py depends on __init__.py). Be advised that this is a bad idea in general but here it is actually fine. The reason for this is that we are not actually using the views in __init__.py and just ensuring the module is imported and we are doing that at the bottom of the file.
If we try to follow what the program does, it is something like that:
app = Flask(__name__) # OK
from views import * # Goes into views.py
from app import app # Looks into app.py, finds it, import it
# Defines home
#app.route('/')
def home():
return "Homepage"
# import home and app, overriding app in app.py
# But views.app is the same as app.app, so it is still
# the same object
# Run main
if __name__=="__main__":
app.run()
I bet it computes something like that. Since app is defined before being imported, it's ok.

Import Handlers - App Route with Flask

My File Directory:
app/
app.py
app/server/
views.py
I don't get any import errors with views, but I am not able to URL route to Views - I can only do it from app.py - how can I fix this issue? I've been stuck on this for 6 hours.
Code from app.py - how I import views
sys.path.append(os.path.join(os.path.abspath('.'), 'server'))
import views
And my url routing seems fine, so I am not sure where the problem lies:
#app.route("/login/", methods=['GET', 'POST'])
def login():
doSomething()
I feel the problem is more to do with url routing than importing files though.
Try from views import * instead of import views.
Also, instead of doing sys.path.append, add an empty file named __init__.py to the server directory, and you should be able to do something like from server.views import *.
Solution: Also make sure your view import is towards the bottom of your app file, below the app initialization and config and such.

Making urls.py file for Flask like in Django

Maybe someone can help/explain me, how to create urls.py file for Flask like in Django?
main.py - main project file. It includes only app runner (app.run()).
urls.py is situated in the same directory and need to provide views
from views.py.
You can do this as is described in the Flask documentation, basically by calling app.add_url_rule to set your routes rather than using the decorator.
In addition to the Flask documentation, this can be solved like this:
When creating the Flask app load your 'urls.py' file
app.register_blueprint(apps.someapp.urls.mod)
Then structure urls.py as following:
from flask import Blueprint
from apps.someapp.views import SomeView
# set method as endpoint
view = SomeView.as_view('someview')
# Create the blueprint for this app
mod = Blueprint("payment_methods", __name__, url_prefix="/someapp/", template_folder="templates")
# Add the view as route; methods like GET, POST, PUT will automatically route to class methods with parameters
mod.add_url_rule('<int:id>/', view_func=view)

Categories