在Python/GAE中声明全局变量的问题
我刚开始学习Python,想从用户界面获取用户名,然后查询这个用户的电话簿联系人。但是我无法把用户名设置为全局变量,以便在多个查询中使用。下面是我的代码,我觉得我可能在语法上出错了或者用法不对,请帮我纠正一下代码。
#!/usr/bin/env python
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
import models
class showPhoneBook(db.Model):
username = db.StringProperty(required=True)
class MyHandler(webapp.RequestHandler):
user_name = ''
def get(self):
p = db.GqlQuery('SELECT * FROM UserDetails WHERE user_name = $1', user_name)
#p = UserDetails.gql('WHERE user_name = $1', user_name)
result1 = p.fetch(1)
for itr1 in result1:
userId = itr.user_id
q = db.GqlQuery('SELECT * FROM PhoneBook WHERE user_id = :1', userId)
#q = PhoneBook.gql('WHERE user_id = :1', userId)
values = {
'phoneBookValues': q
}
self.request.out.write(
template.render('phonebook.html', values))
def post(self):
global user_name
phoneBookuserID = showPhoneBook(
user_name = self.request.get(
'username'))
self.request.out.write(user_name)
phonebookuserID.put()
self.redirect('/')
def main():
app = webapp.WSGIApplication([
(r'.*',MyHandler)], debug=True)
wsgiref.handlers.CGIHandler().run(app)
if __name__ == "__main__":
main()
这里的UserDetails和Phonebook是我在models.py中定义的实体类。
请帮我找出错误……或者给我一个正确的代码,教我如何在从用户界面获取用户名后在查询中使用它。
3 个回答
简单吧!
你似乎把 user_name 存储成了一个类变量,而不是全局变量。在这里有点复杂的地方,就是在方法里引用它会创建一个同名的实例变量,这样就把类变量给隐藏了。
class curious(object):
hide = 11
def get(self):
return self.hide
def put(self,x):
print "before",self.hide
self.hide = x
print "after", self.hide
a = curious()
b = curious()
print a.hide,b.hide
a.put(23)
print a.hide,b.hide
注意,尽管在 a 中改变了值,对象 b 仍然保持着值 11 的引用。
别这么做。要把它真正变成全局变量,应该在模块级别的类定义外面给它赋一个默认值。
这里是Aaron Hampton的回答,内容在Python中在重定向时传递变量到模板。
看起来这个方法可能对你有帮助,而且还能避免其他人提到的全局变量带来的问题。
首先,App Engine的执行方式非常“灵活”,这也是它能扩展的原因!当有人访问你的网址时,GAE可能会重新使用一个已经在运行你脚本的进程,或者它可能会启动另一个进程来运行同样的脚本,这样可以更好地平衡系统的负载;一旦请求处理完毕,处理这个请求的进程可能会继续存在,也可能会消失,这取决于系统是否有更好的方式来利用这个进程占用的内存。
因此,你需要编写代码,使其在这两种情况下都能正常工作,而不能假设进程会在请求之间保持不变(也不能假设它不会保持不变)。所以,全局变量(在各种编程中通常都最好避免使用)绝对不是一个好选择!
在请求之间保持数据的唯一可靠方法是将它们存储在数据库中;另外,将一个cookie发送到用户的浏览器作为响应头,这样浏览器在下一个请求时会把它发回来,这也是可以的(用户可能会选择阻止浏览器接受和发送cookie,但这属于用户的选择,你对此也无能为力)。
抽象的“会话”概念可以封装这些选择,让你在更高的层次上编程,许多框架都提供某种形式的会话,比如可以查看gaeutilities,除非你已经在使用其他提供会话抽象的网络框架。
你的代码中还有许多其他具体问题(比如username
和user_name
之间的混淆,全局变量和类变量之间的混淆,以及对这两者都没有进行任何赋值!),但从某种意义上说,这些问题相比于在App Engine中使用全局变量的整体概念问题来说,算是小问题!-)