Bob5421
Bob5421

Reputation: 9093

how to handle multiple routes in the same class with tornado web server

I am writting a very simple web application with tornado:

class MainHandler1(tornado.web.RequestHandler):
  def get(self):
     self.render("page1.html")

class MainHandler2(tornado.web.RequestHandler):
  def get(self):
     self.render("page2.html")
...

application = tornado.web.Application([(r'/route1', MainHandler1), (r'/route2', MainHandler2)], **settings)

As you can see i have 2 routes, and i need to create 2 classes for those routes. Is there a way to manage several routes with the same class ?

Thanks

Upvotes: 1

Views: 2019

Answers (2)

pagala2008
pagala2008

Reputation: 47

This may be a method

import tornado.ioloop
import tornado.web
from tornado_request_mapping import request_mapping, Route


@request_mapping("/test")
class MainHandler(tornado.web.RequestHandler):
    @request_mapping('/get_by_id', method='get')
    async def test(self):
        self.write("Hello, world. get")

    @request_mapping('/update_by_id', method='post')
    async def test111(self):
        self.write("Hello, world. post")

    @request_mapping("/(\d{4})/(\d{2})/(\d{2})/([a-zA-Z\-0-9\.:,_]+)/?", method='get')
    async def many_args(self, year, month, day, slug):
        # http://localhost:8888/test/2020/11/11/123
        print(year, month, day, slug)
        self.write(f"{year} / {month} / {day} , {slug}")


@request_mapping('/t')
class MyHandler(tornado.web.RequestHandler):
    @request_mapping('/get_by_id', method='put')
    async def test111(self):
        self.write("Hello, world. put")


if __name__ == "__main__":
    app = tornado.web.Application()

    route = Route(app)
    route.register(MainHandler)
    route.register(MyHandler)

    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()


The URL obtained in this way is

GET: http://localhost:8888/test/get_by_id
POST: http://localhost:8888/test/update_by_id
GET: http://localhost:8888/test/2020/11/11/123
PUT: http://localhost:8888/t/get_by_id

Upvotes: 0

Berislav Lopac
Berislav Lopac

Reputation: 17243

Yes, just use the same class in your route specs:

routes = [
    (r'/route1', MainHandler1),
    (r'/route2', MainHandler1)
]
application = tornado.web.Application(routes, **settings)

EDIT re "how will I differentiate route1 and route2 in MainHandler1":

I would suggest you not to tie your handler to any explicit routes; instead try to parametrise it based on variable parts of the route. If we take your original example, where you have two routes differing by a number and serving a different template based on that number, you might have something like:

class MainHandler(tornado.web.RequestHandler):
    def get(self, page_num):
        self.render("page{}.html".format(page_num))

routes = [
    (r'/route(\d+)', MainHandler),
]
application = tornado.web.Application(routes, **settings)

This way you define one route, but effectively have as many as you have templates. On the other hand, if you need a completely different response for each route, it's much better to keep them in separate handlers.

Upvotes: 1

Related Questions