Flask: files in static folder can not be reached (404) - python

I want to serve a react app with flask, but the "static_folder" does not seem to work. This is my very minimal code:
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__, static_folder="react_app/build")
api = Api(app)
class HelloWorld(Resource):
def get(self):
return app.send_static_file("index.html")
api.add_resource(HelloWorld, '/')
if __name__ == '__main__':
app.run(debug=True)
In the browser I can reach http://localhost:5000 and it returns me the correct index.html. But all the static files like css and js files return a 404 error. For example there is a file: react_app/build/bundle.css or react_app/build/js/some_name.js. But typing http://localhost:5000/bundle.css or http://localhost:5000/js/some_name.js both return a 404 not found error.
From what I understand, if I specify a static_folder I should reach all files from that folder from the root url. What am I missing / missunderstanding?

No, that's not what the documentation says:
static_url_path – can be used to specify a different path for the static files on the web. Defaults to the name of the static_folder folder.
static_folder – the folder with static files that should be served at static_url_path. Defaults to the 'static' folder in the root path of the application.
So, your files would be served at localhost:5000/react_app/build. Since that's probably not what you want, you should pass static_url_path as well, with a value of something like "static", so that you can find the files at localhost:5000/static.

Just want to add an important point. Do not forget to add static_url_path='' because it removes any preceding path from the URL (i.e. the default /static).I am not seeing this in you code snippet.
For example,
app = Flask (__name__,
static_url_path='',
static_folder='web/static',
template_folder='web/templates')
static_url_path='' removes any preceding path from the URL (i.e. the
default /static).
static_folder='web/static' to serve any files found
in the folder web/static as static files.
template_folder='web/templates' similarly, this changes the templates
folder.

Related

I have deployed a python flask app on Heroku. The app deploys fine but when I go to view it I get an internal server error [duplicate]

I am trying to render the file home.html. The file exists in my project, but I keep getting jinja2.exceptions.TemplateNotFound: home.html when I try to render it. Why can't Flask find my template?
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
/myproject
app.py
home.html
You must create your template files in the correct location; in the templates subdirectory next to the python module (== the module where you create your Flask app).
The error indicates that there is no home.html file in the templates/ directory. Make sure you created that directory in the same directory as your python module, and that you did in fact put a home.html file in that subdirectory. If your app is a package, the templates folder should be created inside the package.
myproject/
app.py
templates/
home.html
myproject/
mypackage/
__init__.py
templates/
home.html
Alternatively, if you named your templates folder something other than templates and don't want to rename it to the default, you can tell Flask to use that other directory.
app = Flask(__name__, template_folder='template') # still relative to module
You can ask Flask to explain how it tried to find a given template, by setting the EXPLAIN_TEMPLATE_LOADING option to True. For every template loaded, you'll get a report logged to the Flask app.logger, at level INFO.
This is what it looks like when a search is successful; in this example the foo/bar.html template extends the base.html template, so there are two searches:
[2019-06-15 16:03:39,197] INFO in debughelpers: Locating template "foo/bar.html":
1: trying loader of application "flaskpackagename"
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- /.../project/flaskpackagename/templates
-> found ('/.../project/flaskpackagename/templates/foo/bar.html')
[2019-06-15 16:03:39,203] INFO in debughelpers: Locating template "base.html":
1: trying loader of application "flaskpackagename"
class: jinja2.loaders.FileSystemLoader
encoding: 'utf-8'
followlinks: False
searchpath:
- /.../project/flaskpackagename/templates
-> found ('/.../project/flaskpackagename/templates/base.html')
Blueprints can register their own template directories too, but this is not a requirement if you are using blueprints to make it easier to split a larger project across logical units. The main Flask app template directory is always searched first even when using additional paths per blueprint.
I think Flask uses the directory template by default. So your code should be like this
suppose this is your hello.py
from flask import Flask,render_template
app=Flask(__name__,template_folder='template')
#app.route("/")
def home():
return render_template('home.html')
#app.route("/about/")
def about():
return render_template('about.html')
if __name__=="__main__":
app.run(debug=True)
And you work space structure like
project/
hello.py
template/
home.html
about.html
static/
js/
main.js
css/
main.css
also you have create two html files with name of home.html and about.html and put those files in templates folder.
If you must use a customized project directory structure (other than the accepted answer project structure),
we have the option to tell flask to look in the appropriate level of the directory hierarchy.
for example..
app = Flask(__name__, template_folder='../templates')
app = Flask(__name__, template_folder='../templates', static_folder='../static')
Starting with ../ moves one directory backwards and starts there.
Starting with ../../ moves two directories backwards and starts there (and so on...).
Within a sub-directory...
template_folder='templates/some_template'
I don't know why, but I had to use the following folder structure instead. I put "templates" one level up.
project/
app/
hello.py
static/
main.css
templates/
home.html
venv/
This probably indicates a misconfiguration elsewhere, but I couldn't figure out what that was and this worked.
If you run your code from an installed package, make sure template files are present in directory <python root>/lib/site-packages/your-package/templates.
Some details:
In my case I was trying to run examples of project flask_simple_ui and jinja would always say
jinja2.exceptions.TemplateNotFound: form.html
The trick was that sample program would import installed package flask_simple_ui. And ninja being used from inside that package is using as root directory for lookup the package path, in my case ...python/lib/site-packages/flask_simple_ui, instead of os.getcwd() as one would expect.
To my bad luck, setup.py has a bug and doesn't copy any html files, including the missing form.html. Once I fixed setup.py, the problem with TemplateNotFound vanished.
I hope it helps someone.
Check that:
the template file has the right name
the template file is in a subdirectory called templates
the name you pass to render_template is relative to the template directory (index.html would be directly in the templates directory, auth/login.html would be under the auth directory in the templates directory.)
you either do not have a subdirectory with the same name as your app, or the templates directory is inside that subdir.
If that doesn't work, turn on debugging (app.debug = True) which might help figure out what's wrong.
I had the same error turns out the only thing i did wrong was to name my 'templates' folder,'template' without 's'.
After changing that it worked fine,dont know why its a thing but it is.
You need to put all you .html files in the template folder next to your python module. And if there are any images that you are using in your html files then you need put all your files in the folder named static
In the following Structure
project/
hello.py
static/
image.jpg
style.css
templates/
homepage.html
virtual/
filename.json
When render_template() function is used it tries to search for template in the folder called templates and it throws error jinja2.exceptions.TemplateNotFound when :
the file does not exist or
the templates folder does not exist
Create a folder with name templates in the same directory where the python file is located and place the html file created in the templates folder.
Another alternative is to set the root_path which fixes the problem both for templates and static folders.
root_path = Path(sys.executable).parent if getattr(sys, 'frozen', False) else Path(__file__).parent
app = Flask(__name__.split('.')[0], root_path=root_path)
If you render templates directly via Jinja2, then you write:
ENV = jinja2.Environment(loader=jinja2.FileSystemLoader(str(root_path / 'templates')))
template = ENV.get_template(your_template_name)
After lots of work around, I got solution from this post only,
Link to the solution post
Add full path to template_folder parameter
app = Flask(__name__,
template_folder='/home/project/templates/'
)
My problem was that the file I was referencing from inside my home.html was a .j2 instead of a .html, and when I changed it back jinja could read it.
Stupid error but it might help someone.
Another explanation I've figured out for myself
When you create the Flask application, the folder where templates is looked for is the folder of the application according to name you've provided to Flask constructor:
app = Flask(__name__)
The __name__ here is the name of the module where application is running. So the appropriate folder will become the root one for folders search.
projects/
yourproject/
app/
templates/
So if you provide instead some random name the root folder for the search will be current folder.

Flasks blueprint not finding templates or static in root directory

I'm in the midst of refactoring my flask app to use blueprints, and I can't seem to get the blueprint to find the templates or static directories in the app's root directory. The templates/static files are recognised only when I put their folders in the blueprint's directory, which would be fine if the files were used only by that specific blueprint, however I need other modules to be able to access them too (for example the base.html template). I've tried setting the templates & static folder location in the blueprint set up ie.
bp = Blueprint('main', __name__,
template_folder='templates',
static_folder='static')
as well as leaving it blank (in an attempt to get it to default to looking in the root directory)
bp = Blueprint('main', __name__)
I've also tried putting in the path explicitly ie.
template_folder='app/templates'
to no avail.
My app directory looks like this (replaced my names with generic directory names and omitted the other modules as I'm trying to just get this one working first):
library root/
__init__.py
setup.py
app/
venv/
templates/
base.html
home.html
static/
css,js & img files
blueprint/
__init__.py
The library root (app)/__init__.py
looks like this
import os
from flask import Flask
app = Flask(__name__)
def init(app):
#config init...
from app.main import bp as main_bp
app.register_blueprint(main_bp)
print (app.url_map)
init(app)
if __name__ == "__main__":
init(app)
app.run(
host=app.config['ip_address'],
port=int(app.config['port']))
And the blueprint/__init__.py looks like this:
from flask import Blueprint
# Set up a Blueprint
bp = Blueprint('main', __name__,
template_folder='templates',
static_folder='static')
#without setting the template & static locations
#bp = Blueprint('main', __name__)
from flask import render_template
#bp.route('/')
def root():
return render_template('home.html'), 200
My app.url_map output looks like this:
<Rule '/static/<filename>' (HEAD, GET, OPTIONS) -> static>])
Map([<Rule '/' (HEAD, GET, OPTIONS) -> main.root>,
<Rule '/' (HEAD, GET, OPTIONS) -> main.root>,
<Rule '/static/<filename>' (HEAD, GET, OPTIONS) -> static>])
Does anyone have any ideas as to what I'm doing wrong? As far as I was able to see in the various blueprint tutorials around, the default place the app will look for the templates folder is the root directory, followed by the blueprint directory, so why isn't it?
init.py should be under app directory, move it from library root to app directory to solve this issue.

Flask: How to return a website outside of the template directory

I am trying to return websites (html files) that are outside of the template directory.
Directory of the .py file:
archiv/archiv/web/article/articles.py
Directory of the html:
instance/articles/private/abc/abc.html
My articles.py code:
from flask import Blueprint, render_template
bp = Blueprint('articles', __name__, url_prefix='/articles')
#bp.route('/<article>')
def show_article(article):
"""Show a article."""
base_url = '/instance/articles/private/'
url_to_return = base_url + str(article) + '/' + str(article) + '.html'
# return render_template(url_to_return)
return "Hello " + article
The route gets accessed but once i am trying to return the website (comment) i does not work -> template not found. I am pretty sure that render_template isn´t the way to go but i haven´t found anything that could fit.
Could someone show me how to return the website abc.html once the route is called?
Thanks alot in advance
You could add a new template directory when creating the blueprint. When you pass a template name to the render_template function, it will also check the new location.
from flask import Flask, Blueprint, render_template
bp = Blueprint(
'articles',
__name__,
url_prefix='/articles',
template_folder="../instance", # New line!
)
#bp.route('/<article>')
def show_article(article):
"""Show a article."""
return render_template("articles/private/abc.html")
app = Flask(__name__)
app.register_blueprint(bp)
From Flask documentation (for a Blueprint)
template_folder – A folder with templates that should be added to the app’s template search path. The path is relative to the blueprint’s root path. Blueprint templates are disabled by default. Blueprint templates have a lower precedence than those in the app’s templates folder.
If you want to add that template directory to the whole app, you can set template_name when creating Flask instance. Check this for more.

Flask static file giving 404

Code in main.py file:
from flask import Flask, render_template, send_from_directory
app = Flask(__name__, static_url_path="")
app._static_folder = "static"
#app.route("/")
def root():
return app.send_static_file("index.html")
#app.route("/about")
def about():
return app.send_static_file("about/index.html")
#app.route("/projects")
def projects():
return app.send_static_file("projects/index.html")
#snip
if __name__ == "__main__":
app.run(host="0.0.0.0")
When I go to the root directory or the /about directory it works fine, but when I try to go to the /projects directory, I got the error:
Error message:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
There are two possible reasons.
You mis-typed the path. Did you perhaps have a typo in projects (i.e., project) or index.html?
The path doesn't exist. Unlike render_template, app.send_static_file just dies if the path doesn't exist. Since the static_folder is static, then the project page code should exist under static/projects/index.html (and not projects/index.html).
To test if it's a rogue issue, replace the body of the projects view with return 'some string'. If that string doesn't show, then you have a different beast on your hands. If it does, then it's most definitely one of the two bugs I've identified above.
On an un-related note, I would add debug=True to the list of app.run(...) kwargs, to make development more convenient. (The app refreshes whenever there's a file save)

Flask blueprint looks for static file in blueprint instead of root directory

The blueprint I have should look for static files in the root directory but it isn't.
Say I have a blueprint named 'frontend'. 'frontend' only has template_folder='frontend' passed in.
Even if I put the static files under /app/frontend/static/file.css, it doesn't find it. Neither does it find it in /app/static/file.css.
The console webserver says '404' for every css or js static file every time.
But I do have this showing when I print out url_maps:
<Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
I initiated register_blueprint('frontend') like that.
frontend = Blueprint('frontend', __name__,template_folder='templates')
My index in view returns:
return render_template('frontend.html', pagination=pagination)
frontend.html can ONLY work in /app/frontend/templates
If you put frontend.html at /app/templates it does not work there either. Even if you remove the "template_folder" param.
File structure:
app
-app.py
--frontend
--frontend/templates contains: (frontend.html) (base.html) (errors/404.html)
--static
--static/css (bootstrap.min.css) (what I want to grab with url_for inside base.html)
1. Templates
Each flask application, blueprint and module has jinja_loader. When your render_template start find your template it find before in application and then in each blueprint (see get_source and _iter_loader), until not find first exist file.
jinja_loader builds from object path and template folder name, for example, if your application, blueprint or module in /home/www/myapp (/usr/lib/python3.4/site-packages/myapp) folder and template folder than full template folder will be /home/www/myapp/template (/usr/lib/python3.4/site-packages/myapp/template).
It's mean if you have file in application template folder then you render it even if you render template in blueprint. Also if you don't have file in application template folder but in any in blueprint it steel will be rendered. So for blueprints better use unique template prefix to avoid template overriding (falsk_admin - admin/ template prefix).
For example for extension it helps use templates in packages and already have ability replace it in your application if you need it (if you want just inherit you need give new name for template).
2. URL rules
Rules do not have any blueprints prefixes - in blueprint you just concatenate prefix and rule and then use just it.
So all url rules will resolved with exist rules (see another answer https://stackoverflow.com/a/17146563/880326).
You can have same url rule descriptions (/static and /static) and only one endpoint.
3. Static files
For application by default exist static folder. For blueprint you should add static_folder argument. But if both rules will have same descriptions then you can't get files from both by default (with little code can).
For flask application, blueprint and module full static folder dependence form root_path which depends from __name__ argument.
However if you have blueprint without url prefix better set another static_url_path to avoid mistakes.
Try adding static_folder='static' when creating your Blueprint.
Furthermore, you can use the url_for function in jinja to print out your static paths.
{{ url_for(".static", filename="css/bootstrap.min.css") }}

Categories

Resources