How can I use a dispatcher middleware on flask? - python

I am trying to use the wsgi DispatcherMiddleware in order to prefix a url on my application. I've written one module for the dispatcher and one for the app, which has just one view called home and this is where the homepage is served from.
here is my app1.py
import flask
from flask import request, jsonify
app = flask.Flask(__name__)
app.config["DEBUG"] = True
#app.route('/home', methods=['GET'])
def home():
return "<h1>Home</h1>"
and dispatcher.py
from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.exceptions import NotFound
from app1 import app
app = Flask(__name__)
app.wsgi_app = DispatcherMiddleware(NotFound(), {
"/prefix": app
})
if __name__ == "__main__":
app.run()
what I wanna do is be able to navigate to http://127.0.0.1:5000/prefix/home
when I run on console py dispatcher.py, but however when I navigate on that url I get a 404 response. What works in only the navigation to the pagehttp://127.0.0.1:5000/home. Could someone help me understand why this happens? I appreciate any help you can provide

Adding prefix to all routes is really simple if you opt for using Blueprints
https://flask.palletsprojects.com/en/1.0.x/tutorial/views/#create-a-blueprint
from flask import Flask, Blueprint
app = Flask(__name__)
prefixed = Blueprint('prefixed', __name__, url_prefix='/prefixed')
#app.route('/nonprefixed')
def non_prefixed_route():
return 'this is the nonprefixed route'
#prefixed.route('/route')
def some_route():
return 'this is the prefixed route'
app.register_blueprint(prefixed)
if __name__ == "__main__":
app.run()
Testing the routes:
> curl localhost:5000/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
> curl localhost:5000/nonprefixed
this is the nonprefixed route
> curl localhost:5000/prefixed/route
this is the prefixed route

SOLUTION:
I was using wrong tha same name for the dispacher and the app1.
dispacher.py should be edited as follows:
from flask import Flask
from werkzeug.wsgi import DispatcherMiddleware
from werkzeug.exceptions import NotFound
from app1 import app as app1
app = Flask(__name__)
app.wsgi_app = DispatcherMiddleware(NotFound(), {
"/prefix": app1
})
if __name__ == "__main__":
app.run()

Related

404 error constantly encountered when working with Flask

when I run the website on any browser, the typical 404 error "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again." regardless of what I route it to or if I route it at all. I have checked, and everything seems to be in the right place, but I have no idea what is causing the error, especially as I have tried every fix I have found online.
My route.py file is as follows:
from flask import Flask, render_template, url_for
from blog import app, db
from blog.models import User, Post
app = Flask(__name__, template_folder='templates', static_folder='static')
app = Flask(__name__)
#app.route('/')
#app.route("/home")
def home():
posts = Post.query.all()
return render_template('home.html', posts=posts)
#app.route("/about")
def about():
return render_template('about.html', title='About')
The WSGI is:
from blog import app as application
if __name__ == '__main__':
app.run(debug=True)
and the __init__.py file is:
from flask import Flask
import os
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SECRET_KEY'] = 'be35984218226b31d6ca0bf1ccefdaf78e47c9181177a41a'
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'blog.db')
db = SQLAlchemy(app)
from blog import routes
Thanks in advance for any advice given
There are 2 things that could be going wrong:
Your Firewall is blocking the flask app
You entered the wrong IP Address.
If you entered the wrong IP Address, use this IP instead: localhost:5000.
A better alternative would be to use this app.run function instead
app.run(host="0.0.0.0", port=ENTER YOUR DESIRED PORT HERE)
If the firewall is the issue, stackoverflow isn't the right place :/

Flask app doesn't recognize flask_restful resources

I'm trying to build an API with flask_restful, but I don't know how to connect classes that inherit from Resource, with the actual app.
I have the following structure
page
├───api
│ └───__init__.py
│ └───resources.py
└───__init__.py
page/api/resources.py:
from flask_restful import Resource
from page import api
#api.resource("/hello-world")
class HelloWorld(Resource):
def get(self):
return {"hello": "World"}
page/init.py:
from flask import Flask
from flask_restful import Api
from page.config import Config1
api = Api()
def create_app(config_class=Config1):
app = Flask(__name__)
app.config.from_object(config_class)
api.init_app(app)
return app
run.py (outside of the page package):
from page import create_app
if __name__ == "__main__":
app = create_app()
app.run(debug=True)
test:
import requests
BASE = "http://127.0.0.1:5000/"
response = requests.get(BASE + "hello-world")
print(response.json())
Obviously, making a request to "/hello-world" doesn't work. How can I "make Flask aware" of the resources, so that I get a valid response.
Probably there is a much clever way of doing this but for me, the solution would be to remove the decorator #api.resource decorator at page/api/resources.py and make the following changes at page/init.py
from flask import Flask
from page.config import Config1
def create_app(config_class=Config1):
app = Flask(__name__)
app.config.from_object(config_class)
return app
I would also move the run.py inside the page folder and rename it to app.py according to Flask documentation. This app.py should have your routes so change it to something like this:
from page import create_app
from page.api.resources import HelloWorld
from flask_restfull import api
app = create_app()
api = Api(app)
api.add_resource(HelloWorld, '/hello-world')
And to run it just type flask run inside the page folder.

How do I properly declare subdomains in Flask using Blueprint?

I have been following the methods provided in this post:
https://stackoverflow.com/questions/12167729/flask-subdomains-with-blueprint-getting-404
Here is my relevant code:
__init__.py
from flask import Flask, render_template
app = Flask(__name__, static_url_path="", static_folder="static"
import myApp.views
views.py
from flask import Flask, render_template, request, Blueprint
from myApp import app
app.config['SERVER_NAME'] = 'myapp.com'
app.url_map.default_subdomain = "www"
#app.route("/")
def index():
return "This is index page."
test = Blueprint('test', 'test', subdomain='test')
#test.route("/")
def testindex():
return "This is test index page."
app.register_blueprint(test)
if __name__ == "__main__":
app.run()
Using this method I am able to get subdomains 'test' and 'www' working, but now I am unable to access my website via IP address.
Any guidance into the right direction would be appreciated!

NameError: name 'app' is not defined with Flask

I have the following structure in my project
\ myapp
\ app
__init__.py
views.py
run.py
And the following code:
run.py
from app import create_app
if __name__ == '__main__':
app = create_app()
app.run(debug=True, host='0.0.0.0', port=5001)
views.py
#app.route("/")
def index():
return "Hello World!"
_init_.py
from flask import Flask
def create_app():
app = Flask(__name__)
from app import views
return app
I'm trying to use the factory design pattern to create my app objects with different config files each time, and with a subdomain dispatcher be able to create and route different objects depending on the subdomain on the user request.
I'm following the Flask documentation where they talk about, all of this:
Application Context
Applitation Factories
Application with Blueprints
Application Dispatching
But I couldn't make it work, it seems that with my actual project structure there are no way to pass throw the app object to my views.py and it throw and NameError
NameError: name 'app' is not defined
After do what Miguel suggest (use the Blueprint) everything works, that's the final code, working:
_init.py_
...
def create_app(cfg=None):
app = Flask(__name__)
from api.views import api
app.register_blueprint(api)
return app
views.py
from flask import current_app, Blueprint, jsonify
api = Blueprint('api', __name__)
#api.route("/")
def index():
# We can use "current_app" to have access to our "app" object
return "Hello World!"

Flask: why having path converter in root route doesn't work?

from flask import Flask, render_template
app = Flask(__name__, static_url_path='')
#app.route('/')
def index():
return render_template('index.html')
#app.route('/page/<path:page>')
def article(page):
return render_template('page.html')
if __name__ == "__main__":
app.run()
Work just fine. But if i change the second route to #app.route('/<path:page>'), then any access to URL like /path/to/page yields 404.
Why doesn't #app.route('/<path:page>') work?
Related questions, that don't answer the question however:
Flask: Handle catch all url different if path is directory or file
Custom routing in Flask app
Capture arbitrary path in Flask route
static_url_path conflicts with routing. Flask thinks that path after / is reserved for static files, therefore path converter didn't work. See: URL routing conflicts for static files in Flask dev server
works flawless for me:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/page/<path:page>')
def article(page):
return render_template('page.html')
if __name__ == "__main__":
app.debug = True
app.run()
I can access: http://localhost/ -> index and http://localhost/page/<any index/path e.g.: 1> -> article

Categories

Resources