在Google App / Cloud Engine中避免使用Python全局变量

时间:2017-01-08 21:27:43

标签: python google-app-engine global-variables

必须有更好更多的Pythonic方法来做到这一点。我创建了一个小型GAE应用程序来演示我的问题(和无知)。在这里,您可以在输入页面上输入您的姓名。然后,应用程序会问候您,并在每次点击时增加一个数字。效果很好 - 直到其他人同时使用该应用程序,此时一个用户继承另一个用户的名字。

这是因为名称存储在a_state中,是在底部声明的全局(单例)对象吗?如果是这样,我怎样才能确保所有用户都保留自己的名字?提前谢谢!

import webapp2

class AState:
    my_name = "Foo"
    a_number = 42

class GetName(webapp2.RequestHandler):
    def post(self):
        the_state.my_name = self.request.get('the_name')
        self.redirect('/main')

    def get(self):
        self.response.write("""
        <html><body><form action="/" method="post">
            Type your name <input type="text" name="the_name">
            <input type="submit" value="Continue">
        </form></body></html>
        """)


class Main(webapp2.RequestHandler):
    def get(self):
        the_state.a_number += 1
        self.response.write("""
        <html><body><form action="/main" method="get">
        Hello, %s! The number is %d. 
        <input type="submit" value="Keep going">
        </form></body></html>
        """ % (the_state.my_name, the_state.a_number))


app = webapp2.WSGIApplication([
    ('/', GetName),
    ('/main', Main)
], debug=True)

the_state = AState()

注意:在真实的应用程序中,我使用ndb来存储(成功!)应该在所有用户之间共享的信息。我的问题是这个更短暂的,用户特定的信息。

正确的解决方案是咬住子弹并将这些东西存储在数据存储区中吗?

1 个答案:

答案 0 :(得分:0)

从我以前的旧时代开始,我应该知道我要找的那个词是SESSION。万岁 - webapp2也有会议。这是完整的工作代码;它可能会帮助某人尝试让最小的程序正常工作。

关键是为请求定义新的处理程序BaseHandler。您还必须设置配置。请参阅this webapp2 documentation

import webapp2
from webapp2_extras import sessions

class BaseHandler(webapp2.RequestHandler):
    def dispatch(self):
        # Get a session store for this request.
        self.session_store = sessions.get_store(request=self.request)

        try:
            # Dispatch the request.
            webapp2.RequestHandler.dispatch(self)
        finally:
            # Save all sessions.
            self.session_store.save_sessions(self.response)

    @webapp2.cached_property
    def session(self):
        # Returns a session using the default cookie key.
        return self.session_store.get_session()


class GetName(BaseHandler):  # NB: see how we're now inheriting from BaseHandler?
    def post(self):
        self.session['my_name'] = self.request.get('the_name')
        self.session['a_number'] = 42  # NB: setting a session variable
        self.redirect('/main')

    def get(self):
        self.response.write("""
        <html><body><form action="/" method="post">
            Type your name <input type="text" name="the_name">
            <input type="submit" value="Continue">
        </form></body></html>
        """)


class Main(BaseHandler):
    def get(self):
        t_num = self.session.get('a_number') # NB: retrieving a session variable
        t_num += 1
        self.session['a_number'] = t_num

        self.response.write("""
        <html><body><form action="/main" method="get">
        Hello, %s! The number is %d. <input type="submit" value="Keep going">
        </form></body></html>
        """ % (self.session.get('my_name'), t_num))

config = {}
config['webapp2_extras.sessions'] = {
    'secret_key': 'H81%6_(^&k2&)!'     # or some other miscellaneous string
}

app = webapp2.WSGIApplication([
    ('/', GetName),
    ('/main', Main)
], debug=True, config=config)   # NB the config gets added

def main():
    app.run()

if __name__ == '__main__':
    main()