简体   繁体   English

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

[英]Avoiding Python globals in Google App/Cloud Engine

There must be a better and more Pythonic way to do this. 必须有一个更好的,更Python化的方法来做到这一点。 I have created a small GAE app that demonstrates my problem (and ignorance). 我创建了一个小型GAE应用,该应用演示了我的问题(和无知)。 Here you enter your name on an entry page. 在这里,您可以在输入页面上输入姓名。 The app then greets you and increments a number with every click. 然后,该应用程序向您打招呼,并在每次点击时增加一个数字。 Works great -- until someone else uses the app at the same time, at which point one user inherits the other's name. 效果很好-直到其他人同时使用该应用程序时,一个用户才能继承另一个用户的名称。

Is this because the name is stored in a_state , a global (singleton) object declared at the bottom? 这是因为名称存储在a_statea_statea_state是在底部声明的全局(单个)对象? If so, how can I make sure all users keep their own names? 如果是这样,我如何确保所有用户都保留自己的名字? Thanks in advance! 提前致谢!

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()

Note: In the real app, I'm using ndb to store (successfully!) information that should be shared among all users. 注意:在实际应用中,我使用ndb存储(成功!)应在所有用户之间共享的信息。 My problem is with this more ephemeral, user-specific info. 我的问题是有关此更短暂的,特定于用户的信息。

So is the right solution to bite the bullet and store even this stuff in the datastore? 那么,咬紧牙关甚至将这些东西存储在数据存储中的正确解决方案是正确的吗?

From my old php days, I should have known that the term I was looking for was SESSION. 从我以前的php时代开始,我应该知道我所寻找的术语是SESSION。 Hooray -- webapp2 has sessions too. Hooray- webapp2也有会议。 Here is complete working code; 这是完整的工作代码; it may help someone trying to get a minimal program working. 它可能会帮助试图使最低限度的程序工作的人。

The key is to define a new handler for requests, BaseHandler . 关键是为请求定义一个新的处理程序BaseHandler You will also have to set a configuration. 您还必须设置配置。 See this webapp2 documentation . 请参阅此webapp2文档

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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM