Search code examples
pythontornadotornado-motor

how to use coroutine in custom decorator when working with db operations in tornado


I have handlers that handle request with get and post method,i want to use authentication with my own custom decorator,not tornado itself @tornado.web.authenticated decorator. In my custom decorator,i need to query the db to identify the user,but db query in tornado are asynchronously with @gen.coroutine.

My codes are:

handlers.py;

 @account.utils.authentication
    @gen.coroutine
    def get(self, page):

account/utils.py:

@tornado.gen.coroutine
def authentication(fun):
    def test(self,*args, **kwargs    ):
        print(self)
        db = self.application.settings['db']
        result = yield db.user.find()
        r = yield result.to_list(None)
        print(r)
    return test

but the erros occurred when accessed it :

Traceback (most recent call last): File "/Users/moonmoonbird/Documents/kuolie/lib/python2.7/site-packages/tornado/web.py", line 1443, in _execute result = method(*self.path_args, **self.path_kwargs) TypeError: 'Future' object is not callable

can anyone meet this before,what is the correctly way to write custom decorator to authenticate with async db operation ? thanks in advance~


Solution

  • The decorator needs to be synchronous; it's the function it returns that's a coroutine. You need to change:

    @tornado.gen.coroutine
    def authentication(fun):
        def test(self, *args, **kwargs):
            ...
        return test
    

    To:

    def authentication(fun):
        @tornado.gen.coroutine  # note
        def test(self, *args, **kwargs):
            ...
        return test