I have a ReactJS frontend with multiple routes. e.g.: /, /example1, example1/example2/example3/example4.
I have used the react-build script to make production build of the ReactJS app. Now I'm trying to incorporate the ReactJS app with the Flask app.
This is what I have so far on my Flask routes:
app = Flask(__name__, static_folder="./build", static_url_path="")
CORS(app)
app.secret_key = secret_key
#app.route("/", defaults={"path": ""})
#app.route("/<path:path>")
def serve(path):
return app.send_static_file("index.html")
This works, but not for all routes. For example, /example1 and /example1/example2 work. But /example1/example2/example3 doesn't work. Any ideas? Thanks.
EDIT:
It turns out that /example1/example2 does not work, meaning that the issue is to do with custom routes, which aren't predefined. All routes which I have specifically defined work, but the dynamically made ones don't.
https://blog.miguelgrinberg.com/post/how-to-deploy-a-react-router-flask-application - this might help you for now, the tutorial has modified the 404 exception handler (Not really an elegant solution but works).
#app.errorhandler(404)
def not_found(e):
return app.send_static_file('index.html')
Related
I have a Flask app which has a Flask-RestPlus API as well as a "/" route. When I try to access "/" however, I get a 404. If I remove the Flask-RestPlus extension, the route works. How do I make both parts work together?
from flask import Flask
from flask_restplus import Api
app = Flask(__name__)
api = Api(app, doc="/doc/") # Removing this makes / work
#app.route("/")
def index():
return "foobar"
This is an open issue in Flask-RestPlus. As described in this comment on that issue, changing the order of the route and Api solves the issue.
from flask import Flask
from flask_restplus import Api
app = Flask(__name__)
#app.route("/")
def index():
return "foobar"
api = Api(app, doc="/doc/")
flask-restplus defines a different way of assigning routes according to their docs:
#api.route('/')
class Home(Resource):
def get(self):
return {'hello': 'world'}
Notice that the api variable is used instead of the app. Moreover, a class is used although I am not 100% sure it is required.
When in debug mode I want to add a handle to a memcached server in g. A nice place to do that is in the factory create method (create_app in the tutorial).
However, access to g results in a RuntimeError: Working outside of application context. I could register a method using Flask.before_request, but I do not want to have a check for DEBUG mode running every time a user connects.
From what I've read, each request seems to get its own context instance, and with it its own g. Is there another way to retain per-app data for use in this way?
from flask import Flask
from flask import current_app
def create_app():
app = Flask(__name__)
# set your function
setattr(app, 'my_func', 'function')
return app
app = create_app()
#app.route('/')
def index():
return getattr(current_app, 'my_func')
if __name__ == '__main__':
app.run()
I am currently using blueprints in my flask application. However, I would like to define a simple 'base' route ( '/' ) e.g. myapp.com/
How can I do this?
IMHO, this has nothing to do with Flask. To create route to home page, You would do something like this:
#app.route
def index():
return render_template('index.html')
Visiting / on any site where this Flask app is deployed would lead to home page.
Now, in order to lead You to myapp.com/, You need to get myapp.com address, meaning You would need to buy that domain.
I want to use Flask blueprints to organize my Flask-Restful resources into separate url prefixes. Regardless of what url prefix I set (during either blueprint creation or registration), everything gets mapped to the raw route paths. How do I correctly use Restful with blueprints?
app = Flask(__name__)
api = Api(app)
api.add_resource(Building, '/<int:id>', endpoint='building')
api.add_resource(Jack, '/<int:id>', endpoint='jack')
building_api = Blueprint('building_api', __name__)
jack_api = Blueprint('jack_api', __name__)
app.register_blueprint(building_api, url_prefix='/buildings')
app.register_blueprint(jack_api, url_prefix='/jacks')
All documentation I can find says that these should now be available at /buildings/<int:id> and /jacks/<int:id>, but both of those urls 404 and instead I can access the building one at /<int:id>. Hard coding the path in add_resource fixes it, but defeats the point of url_prefix.
You need to pass the blueprint to the Api instance, not the app.
building_bp = Blueprint('buildings', __name__)
building_api = Api(building_bp)
building_api.add_resource(Building, '/<int:id>')
app.register_blueprint(building_bp, url_prefix='/buildings')
This is zhe best way to do with blueprint:
from flask import Flask, Blueprint
from flask_restful import Api, Resource, url_for
app = Flask(__name__)
api_bp = Blueprint('api', __name__)
api = Api(api_bp)
class TodoItem(Resource):
def get(self, id):
return {'task': 'Say "Hello, World!"'}
api.add_resource(TodoItem, '/todos/<int:id>')
app.register_blueprint(api_bp)
you should send Blueprint'instance to Api
I do not know why but I struggled using the Blueprint as mentioned in the answers.
But here's a quick solution I found while going through the doc link. Making use of the prefix parameter in Api() does the job.
app = Flask(__name__)
api = Api(app, prefix='/buildings')
Now, all your routes will be prefixed with /buildings. Just make sure you use url_for('link') in places where you might have simply used a /link.
One more strange thing I noticed is that atleast for me, it did not work until I renamed my routes to the same name as their class names. For example, Class Home(Resource) should have a route to /home. Using /homeepage or any other route for Home Class causes an error. Not sure if it is only me.
I am trying to setup variable route handling in a Flask application such as described in this answer: Dynamic Subdomain Handling in a Web App (Flask)
However, I want to be able to recognize certain subdomains BEFORE they are caught by the variable route so I can use the flask-restful api extension (Routing with RESTful).
For example, I have tried the following:
#app.route('/', subdomain="<user>", defaults={'path':''})
#app.route('/<path:path>', subdomain="<user>")
def user_profile(user,path):
pass
class Api(restful.Resource):
def get(self):
#Do Api things.
api.add_resource(Api, '/v1', subdomain="api")
When I test this, all of URLs go to the variable route handler and call user_prof(). I tried putting the api route first and the standard #app.route rule second and vice versa but there was no change.
Am I missing some other parameter or need to go deeper in Flask to make this happen?
Update:
The URL patterns I am trying to match are like this:
user1.mysite.com -> handled by user_profile()
user2.mysite.com -> handled by user_profile()
any_future_string.mysite.com -> handled by user_profile()
api.mysite.com/v1 -> handled by Api class
Other cases include:
www.mysite.com -> handled by index_display()
mysite.com -> handled by index_display()
#app.before_request
def before_request():
if 'api' == request.host[:-len(app.config['SERVER_NAME'])].rstrip('.'):
redirect(url_for('api'))
#app.route('/', defaults={'path': ''}, subdomain='api')
#app.route('/<path:path>', subdomain='api')
def api(path):
return "hello"
This should work. Add your api version to the path if needed or that could be processed by your API class.
To keep it simple, I redesigned the logic of my application into two distinct parts.
This way the Flask application only handles the API endpoint logic. The user profile logic is handled by another application. I can now add multiple Resources to the API application without worry about breaking the routing.