App.url_for method view that’s not in the same module as app

In the docs, it says that if I am to use method view, that the url_for() should be the class name. https://sanic.readthedocs.io/en/latest/sanic/class_based_views.html

It gives an example of it when that method view is inside the same module as the app. How do I build URLs for method views that are inside other modules?

Assume the view is located here:

my.module.MyMethodView

I have tried these:

url = app.url_for("MethodView")
url = app.url_for("my.module.MyMethodView")

Related + ideally, this should work:

from my module import MyMethodView
url = app.url_for(MyMethodView, foo='bar')

Any help would be appreciated!

Hi @smlbiobot

I’ve done some testing, and this is working as expected for me.

A HTTPMethodView with class named MyMethodView should be queryable from app.url_for() using the string “MyMethodView”. This works no matter which module it is defined in.

from my.module import MyMethodView
app = Sanic(__name__)
app.add_route(MyMethodView.as_view(), "/myroute")
url = app.url_for("MyMethodView")
# --> "/myroute"

Note you have a typo in your first example:
app.url_for("MethodView") -> app.url_for("MyMethodView")

Additionally,
If its still not working for you, you can force the name like this:

from my.module import MyMethodView
app = Sanic(__name__)
app.add_route(MyMethodView.as_view(), "/myroute", name="MyCustomRoute")
url = app.url_for("MyCustomRoute")
# --> "/myroute"

Hey thanks for this — I’ve figured out why it’s not working for me, because I am using blueprints in addition to the method view… so when I do this now it works:

# inside module A

bp_foo = Blueprint('bp_foo')
bp_foo.add_route(SomeView.as_view(), '/path/some')
bp_foo.add_route(OtherView.as_view(), '/path/other/<param>')


# inside module B

class SomeView(BaseView):
	async def get(self, request):
		url = request.app.url_for('bp_foo.OtherView', param='foo')
		return response.redirect(url)


# inside module C

class OtherView(BaseView):
	async def get(self, request, param=None):
		return response.json(dict(ok=True, param=param))


But I had no idea that you can add names to routes — that is good to know!

I don’t know why I didn’t think of this. Might be a good idea to add a remark under this doc page though: https://sanic.readthedocs.io/en/latest/sanic/blueprints.html#url-building-with-url-for

1 Like