Flask can't route to certain url with blueprint - python

I am trying to organize my flask project, but there's something wrong.
I have this directory:
app/
__init__.py
views/
pages.py
On my __init__.py file I've imported the pages object and
registered it as a blue print.
This is the code on my pages.py file.
from flask import Blueprint, render_template
pages = Blueprint('pages', __name__) #no prefix
#pages.route('/')
def index():
return '<h1>in index.html</h1>'
#pages.route('/home')
def home():
return '<h1>in home.html</h1>'
If I run the flask app, open the browser, and go to localhost:5000,
I will see the headline 'in index.html'.
But if I go to localhost:5000/home, I will get the message 404 Not Found message.
Does anyone know the reason for this behavior?

Ok, first the folder structure:
app/
__init__.py
main.py
views/
__init__.py
test.py
Contents of main.py:
from flask import Flask
from views.test import pages
app = Flask(__name__)
app.register_blueprint(pages) <-- blueprint registration
Contents of test.py:
from flask import Blueprint
pages = Blueprint('pages', __name__) #no prefix
#pages.route('/')
def index():
return '<h1>in index.html</h1>'
#pages.route('/home')
def home():
return '<h1>in home.html</h1>'
I believe the register_blueprint was the only thing missing.

When stuff like that happen, just turn off everything, reset your computer.
Sometimes the bug is not yours.

Related

Template error while using Flask with blueprints

I am getting a template not found error while trying to run a flask app using blueprints. The template directory is located at the root directory as expected at the same level as the app directory. I am not very sure why this is happening.
The directory structure
root/
app/
blueprint1/
routes.py
__main__.py
templates/
base.html
index.html
routes.py
from flask import Blueprint, render_template
blueprint = Blueprint(
"blueprint", __name__, template_folder="templates")
#blueprint.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html")
Error
raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: index.html
main.py
from flask import Flask
from app.blueprint1.routes import blueprint
def create_app():
app = Flask(__name__)
app.register_blueprint(blueprint)
return app
def _main():
daemon_app = create_app()
daemon_app.run(debug=True)
if __name__ == "__main__":
_main()
This works, I edited it a little
routes.py
from flask import Blueprint, render_template
blueprint = Blueprint("blueprint", __name__, template_folder="../../templates")
#blueprint.route("/", methods=["GET", "POST"])
def index():
return render_template("index.html")
__main__.py
from flask import Flask
from routes import blueprint
def create_app():
app = Flask(__name__)
app.register_blueprint(blueprint)
return app
def _main():
daemon_app = create_app()
daemon_app.run(debug=True)
if __name__ == "__main__":
_main()`
Based on your file structure, your blueprint renders html files from the main template folder. It might work if you remove the template_folder argument from routes.py file.
I copied your codes and tried to emulate the error but it works for me. A year ago I have the same problem and somehow I solved it. Since I can't emulate the error I can't solve your problem.
Instead, I will just give you advise. You are making an effort to create blueprints in their own package, and yet you are using the main template folder. When you have a lot of blueprints managing the template folder will become a challenge. Thus, I recommend putting the html file within the blueprint package itself.
Here's the file structure:
root/
app/
blueprint1/
pages/blueprint1/index.html
routes.py
__main__.py
templates/
base.html
and routes.py should be like this
blueprint = Blueprint(
"blueprint", __name__, template_folder="pages")
#blueprint.route("/", methods=["GET", "POST"])
def index():
return render_template("blueprint1/index.html")

No name 'routes' in module 'app'pylint(no-name-in-module)

I have a file "init.py" inside have this code
from flask import Flask
app = Flask(__name__)
from app import routes
And in a "routes.py" i have this code
from app import app
#app.route('/')
#app.route('/index')
def index():
user = 'Cala'
return render_template('index.html', user=user)
In the first file in the 3 line say
No name 'routes' in module 'app' pylint(no-name-in-module)
And in the second file in the firts line say
Unable to import 'app' pylint(import-error)
Somebody know what is the problem?, is the fisrt time i do it this is probably is simple or all is wrong. Thanks
The problem in your case is that you didn't put both your files in app directory, since you are using __init__.py file. When doing from app import app it searches for an app directory or app.py file, if directory is not found. If directory is found, it searches for app variable inside __init__.py file.

Import statement flow

My app layout
my_app
__init__.py
my_app
__init__.py
startup
__init__.py
create_app.py
create_users.py
common_settings.py
core
__init__.py
models.py
views.py
errors
__init__.py
errors.py
Inner __init__.py
from flask import Flask
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__) # The WSGI compliant web application object
db = SQLAlchemy(app) # Setup Flask-SQLAlchemy
manager = Manager(app) # Setup Flask-Script
from my_app.startup.create_app import create_app
create_app()
create_app.py
def create_app(extra_config_settings={}):
# Load all blueprints with their manager commands, models and views
from my_app import core
return app
core/__init__.py
# from . import views
views.py
from my_app import app, db
from flask import Flask, request
#app.errorhandler(Error)
def handle_invalid_usage(error):
response = jsonify(data=error.to_dict())
response.status_code = error.status_code
return response
I based this code on a tutorial I found. Everything works fine as long as I leave the __init__.py in the core folder empty.
When I don't, I get a NameError: name Error is not defined in my views.py. Error comes from errors.py.
I have three questions:
1) Why does this happen only when I leave the import statement in core/__init__.py.
2)
create_app.py
app.config.from_envvar('ENV_SETTINGS_FILE')
# Other app.config commands here
from my_app import core
return app
What happens when from my_app import core runs?
3) Finally when I return app, is this to ensure that Inner __init__.py file contains the updated app object?
Any explanations would be greatly appreciated!
Trying to build and configure an app with dynamic imports is really bad news and confusing for the reasons you are discovering. A much better and understandable pattern would be a more typical factory:
def create_app():
app = Flask(__name__)
configure_app(app, config)
register_db(app)
add_views(app)
add_manager(app)
return app
if __name__ == '__main__':
app = create_app()
app.run()
But since you're asking, your problem is here:
from my_app import app, db
from flask import Flask, request
#app.errorhandler(Error) # Error is not imported
def handle_invalid_usage(error):
response = jsonify(data=error.to_dict())
response.status_code = error.status_code
return response
The error occurs because views.py is imported, the code compiler comes across Error and cannot find a reference to it.
For your second question: from my_app import core causes core.__init.__ to run, which (presumably) adds the views onto the app object.

Structuring Flask using Blueprints error

I'm attempting to break a small app into units and use the Blueprint pattern in Flask. However I seem to have trouble in getting the app running.
Here is my structure:
\myapp
login.py
\upload
__init__.py
views.py
Here is login.py:
import sys, os
from flask import Flask, Blueprint, request
from flask import render_template, session
from .upload import views
app = Flask(__name__)
app.register_blueprint(views)
#app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
print app.url_map
print app.blueprints
app.run(debug = True)
for __init__.py
from flask import Flask
app.register_blueprint('upload', __name__)
and in views.py
from flask import Flask, Blueprint, request, redirect, url_for, render_template
import views
upload = Blueprint('upload', __name__)
#upload.route('/uploaded', methods=['GET', 'POST'])
def upload_file():
...
Looking at the logs on heroku, here is the error:
from .upload import views
2015-09-05T10:59:00.506513+00:00 app[web.1]: ValueError: Attempted relative import in non-package
Have a structured my package and blueprint correctly? I used the documentation, but I think I'm missing something here.
There are three problems with your code:
You are using a relative import in login.py to include views, but given the folder structure and the fact that you use login.py as starting point, it cannot work here. Simply use from upload import views instead.
The __init__.py references an unknown variable, app. You actually don't need anything in this file, remove everything.
You try to register a module as a blueprint via app.register_blueprint(views) in login.py. This cannot work, a module is not a blueprint. Instead, import the upload variable defined in the views module, that is a blueprint: app.register_blueprint(views.upload).
Changing that should get you started. Two side notes:
You have an import in views.py that should probably not be there: import views. This should be harmless however.
I answered a question about Flask blueprints some days ago, and gave an example about how to use them. Maybe would you find the answer useful in your case as well (in particular the part where the blueprint definition is moved to the __init__.py file defining the blueprint).

Flask unable to find templates

My project structure is like below
run.py
lib/
mysite/
conf/
__init__.py (flask app)
settings.py
pages/
templates/
index.html
views.py
__init__.py
This is mysite.conf.__init__
from flask import Flask
app = Flask(__name__)
app.debug = True
My idea is to now import app to every other module to use it to create views. Here in this case there is a module pages.
In pages.views I have some code like
from flask import render_template
from mysite.conf import app
#app.route('/')
def index():
return render_template('index.html')
The index.html is placed in pages/templates
When I run this app from run.py which is like below
from mysite.conf import app
app.run()
I'm getting template not found error.
How to fix it? and why is this happening!
I'm basically a django guy, and facing a lot of inconvenience with importing the wsgi object every time to create a view in every module! It kinda feels crazy -- Which in a way encourages circular imports. Is there any way to avoid this?
Flask expects the templates directory to be in the same folder as the module in which it is created; it is looking for mysite/conf/templates, not mysite/pages/templates.
You'll need to tell Flask to look elsewhere instead:
app = Flask(__name__, template_folder='../pages/templates')
This works as the path is resolved relative to the current module path.
You cannot have per-module template directories, not without using blueprints. A common pattern is to use subdirectories of the templates folder instead to partition your templates. You'd use templates/pages/index.html, loaded with render_template('pages/index.html'), etc.
The alternative is to use a Blueprint instance per sub-module; you can give each blueprint a separate template folder, used for all views registered to that blueprint instance. Do note that all routes in a blueprint do have to start with a common prefix unique to that blueprint (which can be empty).
I ran in to this problem as well being brand new to Flask.
The solution for my situation was to create an __init__.py file in the main app directory so as to turn app/ in to a module since, as Martijn Pieters pointed out, flask expects templates to be in the main module directory by default. And to restate from his answer, you can reassign the default directory when instantiating the Flask class, e.g. Flask(__name__, template_folder=any/relative/path/from/app/dir/or/absolute/path/youd/like)
A simple directory structure should therefore look like this:
app/
run.py
templates/
sample_template.html
__init__.py # <---- This was the missing file in my case.
... where app.py might look like this:
from flask import Flask, render_template
app = Flask(__name__) # or e.g. Flask(__name__, template_folder='../otherdir')
#app.route("/")
def home():
return "Hello world"
#app.route("/hello/again")
def hello_again():
return render_template("hello_again.html")
if __name__ == "__main__":
app.run()
I'm pretty sure you made a mistaking spelling "template" on main folder. Just rename it
or:
do something like this (template_folder = 'the name of the folder your file belongs to')
from flask import Blueprint
from flask import render_template
views = Blueprint('views',__name__,template_folder='tamplate')
#views.route('/')
def home():
return render_template("home.html")

Categories

Resources