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)
Related
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.
I have a Flask back-end with API routes which are accessed by a React single page application created using create-react-app. When using the create-react-app dev server, my Flask back end works.
I would like to serve the built (using npm run build) static React app from my Flask server. Building the React app leads to the following directory structure:
- build
- static
- css
- style.[crypto].css
- style.[crypto].css.map
- js
- main.[crypto].js
- main.[crypto].js.map
- index.html
- service-worker.js
- [more meta files]
By [crypto], I mean the randomly generated strings generated at build time.
Having received the index.html file, the browser then makes the following requests:
- GET /static/css/main.[crypto].css
- GET /static/css/main.[crypto].css
- GET /service-worker.js
How should I serve these files? I came up with this:
from flask import Blueprint, send_from_directory
static = Blueprint('static', __name__)
#static.route('/')
def serve_static_index():
return send_from_directory('../client/build/', 'index.html')
#static.route('/static/<path:path>') # serve whatever the client requested in the static folder
def serve_static(path):
return send_from_directory('../client/build/static/', path)
#static.route('/service-worker.js')
def serve_worker():
return send_from_directory('../client/build/', 'service-worker.js')
This way, the static assets are successfully served.
On the other hand, I could incorporate this with the built-in Flask static utilities. But I do not understand how to configure this.
Is my solution robust enough? Is there a way to use built-in Flask features to serve these assets? Is there a better way to use create-react-app?
import os
from flask import Flask, send_from_directory
app = Flask(__name__, static_folder='react_app/build')
# Serve React App
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def serve(path):
if path != "" and os.path.exists(app.static_folder + '/' + path):
return send_from_directory(app.static_folder, path)
else:
return send_from_directory(app.static_folder, 'index.html')
if __name__ == '__main__':
app.run(use_reloader=True, port=5000, threaded=True)
Thats what I ended up with. So bascially catch all routes, test if the path is a file => send file => else send the index.html. That way you can reload the react app from any route you wish and it does not break.
First do npm run build to build the static production files as mentioned by you above
from flask import Flask, render_template
app = Flask(__name__, static_folder="build/static", template_folder="build")
#app.route("/")
def hello():
return render_template('index.html')
print('Starting Flask!')
app.debug=True
app.run(host='0.0.0.0')
Unfortunately, I don't think you can get it work with the development hot-reload.
A working solution here.
Ever thought why we need two separate folders for static and templates. To segregate the mess, right?
But, it's a problem with the production build since it has one folder for both static and templates type of files and all dependencies are linked like that.
The build folder will be served if you consider it both static and templates.
Use something like this
from flask import Flask, render_template
app = Flask(__name__, static_url_path='',
static_folder='build',
template_folder='build')
#app.route("/")
def hello():
return render_template("index.html")
Your flask app will run fine.
The accepted answer does not work for me. I have used
import os
from flask import Flask, send_from_directory, jsonify, render_template, request
from server.landing import landing as landing_bp
from server.api import api as api_bp
app = Flask(__name__, static_folder="../client/build")
app.register_blueprint(landing_bp, url_prefix="/landing")
app.register_blueprint(api_bp, url_prefix="/api/v1")
#app.route("/")
def serve():
"""serves React App"""
return send_from_directory(app.static_folder, "index.html")
#app.route("/<path:path>")
def static_proxy(path):
"""static folder serve"""
file_name = path.split("/")[-1]
dir_name = os.path.join(app.static_folder, "/".join(path.split("/")[:-1]))
return send_from_directory(dir_name, file_name)
#app.errorhandler(404)
def handle_404(e):
if request.path.startswith("/api/"):
return jsonify(message="Resource not found"), 404
return send_from_directory(app.static_folder, "index.html")
#app.errorhandler(405)
def handle_405(e):
if request.path.startswith("/api/"):
return jsonify(message="Mehtod not allowed"), 405
return e
I used a flask server with only one route / which read the index.html file from the build folder of Create react app(CRA)
from flask import Flask
app = Flask(__name__)
app.static_folder = '../build'
#app.route('/')
def index():
fref = open(r'../build/index.html')
html_text = fref.read()
fref.close()
return html_text
app.run()
Setting up this way I faced an error, the static files are not properly served due to path mismatch, so the solution I used is
Add a homepage property in package.json of CRA and set it to "/static"
{
"name":"App-name",
"version":"",
"dependencies":{}
"homepage":"/static",....[other keys]}
Add **homepage** key parallel to the **dependencies** key in the package.json file
This homepage property will be used during the build process of CRA and used in the place of %PUBLIC_URL% of index.html and gets appended to other static assets URL path (you can verify by viewing the index.html code after the build process)
After the build process, run the flask server,we can see the GET request coming with / for the first time and index.html will be served and followed by requests /static/static/js/[[filename]] for other static assets from HTML file and everything works correctly
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.
I have a website that uses Flask. It used to work well, but since recently, every request returns a 404, and it seems it can't find the right endpoints. However:
Locally, the site still works, only on my VPS it shows this strange behaviour.
url_for works and app.view_functions contains all the routes as well.
And yet, I keep getting 404s on the VPS, even for / and anything under /static/.
Here's part of the code, it's a bit much to show all of it and it's not all relevant:
#snip
from flask import Flask, render_template, abort, request, redirect, url_for, session
from flask.ext.babelex import Babel
from flask.ext import babelex
#snip
app = Flask(__name__)
app.secret_key = #snip
#snip
#just one of the routes
#app.route('/')
def about():
return render_template('about.html')
#snip
#app.errorhandler(404)
def page_not_found(e):
#snip
return render_template('404.html'), 404
#snip
if __name__ == '__main__':
app.run(debug=True)
else:
app.config.update(
SERVER_NAME='snip.snip.com:80',
APPLICATION_ROOT='/',
)
I had the same issue. I had it because I changed the parameters SERVER_NAMEof the config to a name which is not the name of the server.
You can solve this bug by removing SERVER_NAME from the config if you have it.
I know this is old, but I just ran into this same problem. Yours could be any number of issues but mine was that I had commented out the from app import views line in my __init__.py file. It gave me the same symptom: every endpoint that required #app.route and a view was responding with 404's. Static routes (.js and .css) were fine (that was my clue).
Had the same issue because the following lines
if __name__ == '__main__':
app.run(host='127.0.0.1', threaded=True)
were declared before the function and decorator.
Moving these lines in the very bottom of file helped me.
Extremely old by this point, but mine was related to bug in importing. I'm using blueprints and I had:
from app.auth import bp
instead of
from app.main import bp
I was importing the wrong bp/ routes
I received this error from defining my flask_restful route inside the create_app method. I still don't quite understand why it didn't work but once I changed the scope / moved it outside as shown below it worked.
from flask import Flask
from flask_restful import Resource
from extensions import db, api
from users.resources import User
def create_app():
app = Flask(__name__)
app.config.from_object('settings')
db.init_app(app)
api.init_app(app)
return app
api.add_resource(User, '/users')
Also check carefully the routes. If some does not end with a slash but you are calling it with a trailing slash, flask will return a 404.
I had this error following a url from an email client that (I don't know why) append a trailing slash to the urls.
See documentation.
I had this problem and in my case it was about my templates. I had an index page like this:
<div>
Home |
Login |
Register
<hr>
</div>
I should have used url_for('index') instead of index.html.
<div>
Home |
Login |
Register
<hr>
</div>
For me, I was getting 404s on every request due to missing favicon.ico and manifest.json. The solution was to provide the missing favicon.ico, and remove the link rel refence to manifest.json.
I found this out by printing the path that was causing problems on every request in my #app.errorhandler(Exception):
from flask import request
#app.errorhandler(Exception)
def handle_exception(err):
path = request.path # this var was shown to be 'favicon.ico' or 'manifest.json'
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.