Flask unable to find templates - python

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

Related

How to access functions in packages in Flask? [duplicate]

My flask application currently consists of a single test.py file with multiple routes and the main() route defined. Is there some way I could create a test2.py file that contains routes that were not handled in test.py?
#app.route('/somepath')
def somehandler():
# Handler code here
I am concerned that there are too many routes in test.py and would like to make it such that I can run python test.py, which will also pick up the routes on test.py as if it were part of the same file. What changes to I have to make in test.py and/or include in test2.py to get this to work?
You can use the usual Python package structure to divide your App into multiple modules, see the Flask docs.
However,
Flask uses a concept of blueprints for making application components and supporting common patterns within an application or across applications.
You can create a sub-component of your app as a Blueprint in a separate file:
simple_page = Blueprint('simple_page', __name__, template_folder='templates')
#simple_page.route('/<page>')
def show(page):
# stuff
And then use it in the main part:
from yourapplication.simple_page import simple_page
app = Flask(__name__)
app.register_blueprint(simple_page)
Blueprints can also bundle specific resources: templates or static files. Please refer to the Flask docs for all the details.
You can use simple trick which is import flask app variable from main inside another file, like:
test_routes.py
from __main__ import app
#app.route('/test', methods=['GET'])
def test():
return 'it works!'
and in your main files, where you declared flask app, import test-routes, like:
app.py
from flask import Flask, request, abort
app = Flask(__name__)
# import declared routes
import test_routes
It works from my side.
This task can be accomplished without blueprints and tricky imports using Centralized URL Map
app.py
import views
from flask import Flask
app = Flask(__name__)
app.add_url_rule('/', view_func=views.index)
app.add_url_rule('/other', view_func=views.other)
if __name__ == '__main__':
app.run(debug=True, use_reloader=True)
views.py
from flask import render_template
def index():
return render_template('index.html')
def other():
return render_template('other.html')
I would like to recommend flask-empty at GitHub.
It provides an easy way to understand Blueprints, multiple views and extensions.
If you need split blueprint to separate files you can use snippet:
# app.py
from blueprint_module import blueprint
app = Flask(__name__)
app.register_blueprint(blueprint)
# blueprint_module\__init__.py
from flask import Blueprint
blueprint = Blueprint('my_blueprint', __name__)
from . import page
# blueprint_module\page.py
from . import blueprint
#blueprint.route("/url", methods=['GET'])
def hello():
return 'hello world'
Dividing the app into blueprints is a great idea. However, if this isn't enough, and if you want to then divide the Blueprint itself into multiple py files, this is also possible using the regular Python module import system, and then looping through all the routes that get imported from the other files.
I created a Gist with the code for doing this:
https://gist.github.com/Jaza/61f879f577bc9d06029e
As far as I'm aware, this is the only feasible way to divide up a Blueprint at the moment. It's not possible to create "sub-blueprints" in Flask, although there's an issue open with a lot of discussion about this:
https://github.com/mitsuhiko/flask/issues/593
Also, even if it were possible (and it's probably do-able using some of the snippets from that issue thread), sub-blueprints may be too restrictive for your use case anyway - e.g. if you don't want all the routes in a sub-module to have the same URL sub-prefix.

Flask can't route to certain url with blueprint

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.

Order of registering Flask Blueprints

I ran into a strange issue (maybe not so strange for experienced in flask).
I have a flask application running in the context of Google App Engine's dev_appserver.py
I have a blueprint in my flask application
# rest_server.py
rest_api = Blueprint('rest_api', __name__)
app = Flask(__name__)
app.register_blueprint(rest_api, url_prefix='/api') # [1] DOESN'T WORK
#rest_api.route("/")
def hello():
return "Hello World"
app.register_blueprint(rest_api, url_prefix="/api") # [2] WORKS AS EXPECTED
I have the following in my app.yaml
-url: "/api/.*"
script: rest_server.app
When I hit localhost:8080/api/ when I register blueprint at position [1], I get an error saying there is no matching endpoint.
However, when I register bluerpint at [2], any position after the decorator, it works.
Is it required to register the blueprint after all the decorators?
Yes, it's required to register blueprints only after all their routes have been declared, at least if you want to use those routes. (If you don't mind the routes not being available, it doesn't look like there's actually any problem with declaring new routes after registering the blueprint.)
If you want to know why: basically, blueprint url rules are only registered on the application when Flask.register_blueprint is called. If you add routes after registering the blueprint, they just get added to the list of things to do when the blueprint is registered (Blueprint.deferred_functions), they don't get retroactively added to any existing applications that the blueprint was registered to in the past.
Though you have registered your blueprint, it is not actually registered!
the point is that your application is not aware of existence rest_server.py
You have to register it in the same file in which you have the following code:
app = Flask(__name__)
This should solve your problem.
I'd like to show the pattern of using blueprints I use.
(It is useful for a better organization of your code) :
Blueprint Pattern
your application can look like this:
/yourapplication
runserver.py
/application #your application is a package containing some blueprints!
__init__.py
models.py
/hello #(blueprint name)
__init__.py
views_file1.py
views_file2.py
your runserver.py should look like this:
# runserver.py
from application import app
app.run()
In this example, hello is a package and one of your blueprints:
# application/hello/__init__.py
from flask import Blueprint
hello = Blueprint('main', __name__)
# import views of this blueprint:
from application.hello import views_file1, views_file2
Import and register your blueprints in application/__ init__.py. your application/__ init__.py should look like this:
# application/__init__.py
from flask import Flask
from .hello import hello as hello_blueprint
app = Flask(__name__)
app.register_blueprint(hello_blueprint)
from application.models import * #your models (classes, or *)

render_template from Flask blueprint uses other blueprint's template

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.

Running the flask/python code in linux? Basic flask code

I have been learning flask/ python from this tutorial http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
This blog is pretty good and it explain very well. In the first tutorial, if you notice,
he asks us to create a init.py file, a views.py file and a main run.py file.
root
/microblog
/apps
/__init__.py
views.py
I created the two files. He asks us to create a run.py file and put it in the root file. then
chmod a+x run.py
./run.py
It says the file does not exist.
If I,
python run.py
It says App module not defined.
I cannot figure out the problem, I put the run.py file in all the files, it doesnt not work what so ever.
I will also include the code so that it would be easier to answer instead of going to the above link
init.py
from flask import Flask
app = Flask(__name__)
from app import views
views.py
from app import app
#app.route('/')
#app.route('/index')
def index():
return 'Hello world'
run.py
#!flask/bin/python
from app import app
app.run(debug = True)
My questions:
Where should I put the run.py file?
Why are we creating different files? Why cant all of them be in one
full file?
init.py -->
he is importing flask which is normal. then assigning app =
(name). why is that? Then why is he importing views from apps?
views.py -->
from app import app? is app an existing module here or the one we
just created? what does #app.route('/') or
#app.route('/index')do?
Can some one put the code together and explain it?
It says App module not defined
You misspelled package name: you have apps in your directory tree and you try to import app
Where should I put the run.py file?
Anywhere you want as long app is in PYTHONPATH. Or you can put it inside microblog directory.
he is importing flask which is normal. then assigning app = (name). why is that?
# Create reference to flask WSGI application object
app = Flask(__name__)
Why? Because you need application to run. See official docs: Flask object
Then why is he importing views from apps?
from app import views
means: From package named app import module named views
Naming convention could be probably different but if you don't see the difference you should probably spend more learning python basics before starting with more sophisticated stuff.
from app import app? is app an existing module here or the one we just created? what > does #app.route('/') or #app.route('/index')do?
#app.route('/')
def index():
return 'Hello world'
Short answer: if app receives request for url '/' responds using function foo
For more see official docs: add_url_rule and URL Route Registrations
Update
Why are we creating different files? Why cant all of them be in one full file?
Actually nothing stops you from putting everything inside one file but most of the time it is really bad idea. If you ask about reasoning in this specific example it is mostly about separating modules that have different responsibilities.

Categories

Resources