Reputation: 23459
I want to define routes manually to some method of classes, something like this :
class X:
def route1():
#do stuff here
def route2():
#do stuff here
and then make something like this :
app.add_url_rule('/x/', view_func=X.route1())
app.add_url_rule('/y/', view_func=X.route2())
It's possible?? What's the correct way to acomplish this?
Upvotes: 11
Views: 9470
Reputation: 4106
If you're talking about flask
's helper decorator, app.route(...)
, don't forget, it's just a decorator, and you can always just call
the returned wrapper of a decorator.
With a nonsense, do-nothing wrapper like,
def some_wrapper():
def wrapper(fn):
return fn()
return wrapper
When you wrap a func like,
@some_wrapper
def some_func():
print('Hello World')
For all intents and purposes, what might as well be happening is,
def some_func():
print('Hello World')
some_func = some_wrapper()(some_func)
So, because of that, you can call app.route
just like you can any decorator,
app.route('/x/')(X.route1)
This ends up doing exactly the same as @sean-vieira's bit of his answer - app.add_url_rule('/x/', view_func=INSTANCE_X.route1)
.
But one reason you might prefer it is because it follows the "regular" path of flask, and flask docs.
For my use, the reason I use it is to chain some routes which I add programatically,
suffix = 'ducky'
app.route(f'secure_initial_route_for_{suffix}', endpoint=f'secure_{suffix}')(
roles_required('admin')(secured_fn))
app.route(f'secure_sub_route_for_{suffix}', endpoint=f'secure_sub_{suffix}')(
roles_required('admin')(secured_sub_fn))
That is how I some of my use cases.
Upvotes: 0
Reputation: 177
Like I said in the comments, do you know flask-classy?
From their exemple:
from flask import Flask
from flask.ext.classy import FlaskView
# we'll make a list to hold some quotes for our app
quotes = [
"A noble spirit embiggens the smallest man! ~ Jebediah Springfield",
"If there is a way to do it better... find it. ~ Thomas Edison",
"No one knows what he can do till he tries. ~ Publilius Syrus"
]
app = Flask(__name__)
class QuotesView(FlaskView):
def index(self):
return "<br>".join(quotes)
def get(self, id):
id = int(id)
if id < len(quotes) - 1:
return quotes[id]
else:
return "Not Found", 404
QuotesView.register(app)
if __name__ == '__main__':
app.run()
Would generate automatically routes for http://foobar.foo/quotes
and http://foobar.foo/quotes/<id>
Upvotes: 5
Reputation: 160073
There are several ways to do this:
Create a global instance of your class and route your rules to it:
class X(object):
# Your code here
INSTANCE_X = X()
# Note that we are not *calling* the methods
app.add_url_rule('/x/', view_func=INSTANCE_X.route1)
app.add_url_rule('/y/', view_func=INSTANCE_X.route2)
Create an instance in the view function and delegate to it:
# Using both methods of registering URLs here
# just to show that both work
@app.route('/x/')
def handle_route1():
return X().route1()
def handle_route2():
return X().route2()
app.add_url_rule('/y/', view_func=handle_route2)
Inherit from Flask's View
or MethodView
Pluggable View classes and use the as_view
classmethod to handle this for you:
class X(View):
methods = ['GET']
def dispatch_request(self):
if request.path == '/x/':
return route1()
elsif request.path == '/y/':
return route2()
else:
abort(404)
app.add_url_rule('/x/', view_func=X.as_view('X.route1'))
app.add_url_rule('/y/', view_func=X.as_view('X.route2'))
Upvotes: 14