Jim
Jim

Reputation: 829

tornado throw can' write() after finish()

I have a custom authenticated decorator, and add on each get and post method to authenticate and after authenticated,do some db query and update,but when i yield update() using motor, throw can't write after finish() error

account/utils.py:

def authentication(fun):
    """
    decorator for authenticating  whether a user is logged in or not

    :param fun:
    :return:
    """
    @tornado.gen.coroutine
    def wrapper(self, *args, **kwargs):
        db = self.application.settings['db']

        if kwargs['token'] != None:
            session = yield db.session.find_one({'token': kwargs['token']},{'uid'})
            if session != None:
                kwargs['uid'] = session['uid']
                raise gen.Return(fun(self, *args, **kwargs))
            else:
                self.write({'status':0,'message':'请登录',"data":{}})
        else:
            self.write({'status':0, 'message':'请登录', 'data':{}})
    return wrapper

wall.handlers.py:

@account.utils.authentication
    @gen.coroutine
    def post(self, *args, **kwargs):
        """
        post a new kuolie card
        :param args:
        :param kwargs:
        :return:
        """
        print('sss')
        db = self.settings['db']
        up = upyun.UpYun('kuolie-img', username='jinpeng', password='jinpengjinpeng')
        uid = kwargs['uid']
        request_data = json.loads(self.request.body)

        user_docs = dict(

        )
        if 'nickname' in request_data.keys():
            user_docs['nickname'] = request_data['nickname']
        if 'qq' in request_data.keys():
            user_docs['qq'] = request_data['qq']
        if 'phone' in request_data.keys():
            user_docs['phone'] = request_data['phone']
        if 'weibo' in request_data.keys():
            user_docs['weibo'] = request_data['weibo']
        if 'weixin' in request_data.keys():
            user_docs['weixin'] = request_data['weixin']
        if 'level' in request_data.keys():
            user_docs['level'] = request_data['level']
        if 'meta' in request_data.keys():
            user_docs['meta'] = request_data['meta']
        if 'avatar' in request_data.keys():
            user_docs['avatar'] = request_data['avatar']
        if 'gender' in request_data.keys():
            user_docs['gender'] = request_data['gender']
        if 'kuolietext' in request_data.keys():
            user_docs['kuolietext'] = request_data['kuolietext']
        if 'kuolieimage' in request_data.keys():
            user_docs['kuolieimage'] = request_data['kuolieimage']
        if 'kuolieaudio' in request_data.keys():
            user_docs['kuolieaudio'] = request_data['kuolieaudio']


        user_docs['time'] = int(time.time())
        result = yield db.user.update({'uid': uid}, {'$set': user_docs })
        print result
        if result['updatedExisting'] == True:
            print('true')
            self.write({'status':1,'message':'添加成功','data':{}})

when post request arrives,the decorator authenticated the user,if authenticated ,then do the update,but there is an error:

[E 160503 17:16:00 concurrent:124] Future exception was never retrieved: Traceback (most recent call last): File "/Users/moonmoonbird/Documents/kuolie/lib/python2.7/site-packages/tornado/gen.py", line 1017, in run yielded = self.gen.send(value) File "/Users/moonmoonbird/Documents/kuolie/kuolie/wall/handlers.py", line 65, in get self.write({'status':1,'message':'认证通过',"data":{"a":'b'}}) File "/Users/moonmoonbird/Documents/kuolie/lib/python2.7/site-packages/tornado/web.py", line 685, in write raise RuntimeError("Cannot write() after finish()") RuntimeError: Cannot write() after finish()

am i doing wrong ,can someone help me, thanks in advance.

Upvotes: 0

Views: 1438

Answers (1)

Ben Darnell
Ben Darnell

Reputation: 22154

The wrapper needs to use yield when calling fun, which is also a coroutine:

raise gen.Return(yield fun(self, *args, **kwargs))

If you need to support both coroutines and non-coroutines with the same wrapper, check the return value:

ret = fun(self, *args, **kwargs)
if ret is not None:  # handlers are not supposed to return anything but None
    ret = yield ret
raise gen.Return(ret)

Upvotes: 2

Related Questions