对于一个数据量大的网站应用来说数据存储是个很有技巧的的事情。用户可能在一个特定的时间发出了一个数据请求,但是下一个时间又发出了另外一个完全不同的数据请求。所有的WEB服务都需要协调这些相互影响的请求,并且这些请求可能来自世界的各个地方。
由于有了Google App Engine,你再也不需要为这些发愁了。Google App Engine架构将为提供分布式的数据处理,解决负载平衡的问题,并且提供了API来实现所有关于数据存储的问题。
数据存储完整实例
下面是一个最新版的 helloworld/helloworld.py 代码,用来存储用户的留言。下面的所有文字都是用来解释这段代码的。
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
for greeting in greetings:
if greeting.author:
self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>""")
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', MainPage),
('/sign', Guestbook)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
将上面的代码替换掉 helloworld/helloworld.py 原有的代码,然后重新加载 http://localhost:8080/ 试着发布一条留言,看看你的留言是否被正确地存储并且正常地显示了。
存储用户提交的留言
App Engine 包含了一个基于Python的数据存储模型. 这个模型类似于 Django's data modelling API, 但是使用了Google自己的存储环境.
对于上一章实现的留言程序,我们想要把用户提交的留言保存起来,每个留言都包含作者名称,消息内容,发布时间等等,并且按照留言的先后将其显示出来。
为了使用data modeling API,在代码顶部添加 google.appengine.ext.db 模块:
from google.appengine.ext import db
下面的这段代码定义了一个用来存储用户留言的模块:
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
这段代码定义了 Greeting 模型的三个属性: author 是一个 User 对象, content 是一个字符串对象,anddate 是一个datetime.datetime对象。
其中一些属性包含了默认值:比如db.StringProperty 类型中 multiline=True 表明该字符串中可以包含换行符;db.DateTimeProperty类型中 auto_now_add=True 表明当Greeting对象创建的时候,将使用当前时间初始化这个属性。关于数据模型的属性的更多帮助,请查看 the Datastore reference。
既然我们已经定义了一个数据对象模型,接下来,我们创建一个Greeting对象,并且把它保存起来。编辑 Guestbook handler :
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/')
这个新的 Guestbook handler 创建了一个新的 Greeting 对象,然后根据用户提交的数据设置 author 和 content 的属性值。 它并没有甚至 date 的值,所以 date 会自动设成当前时间,因为我们在模型建立的时候已经设置了。
最后一行, greeting.put() 将新创建的对象保存进数据库,如果put()进去的是从数据库中提取的对象,put() 会更新那条数据记录,而现在我们是新创建的一个对象,所以 put() 会添加一条新的记录到数据存储里。
使用 GQL 获取数据记录
App Engine datastore 使用了一套复杂的数据储存系统.但是它并不是一个标准的关系数据库,所以不能使用标准的Sql语句进行查询。作为一个替代,Google准备了一套类Sql的查询语句,称之为GQL.GQL 提供了和SQL基本类似的语法来读取数据。
下面是新版的 MainPage handler 代码,用来查询数据库中的所有留言。
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
for greeting in greetings:
if greeting.author:
self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/sign" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
</body>
</html>""")
查询语句出现在这一行:
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
或者,你也可以在Greeting类里面调用 gql(...) 方法,那样就不必使用 SELECT * FROM Greeting 这样的查询语句了:
greetings = Greeting.gql("ORDER BY date DESC LIMIT 10")
和SQL语句类似,关键字 (比如 SELECT) 是大小写无视的,字段名是区分大小写的。
要注意的是,GQL语句总是返回完整的对象,所以GQL查询语句不能指定要查询的字段名。也就是说,所有的GQL语句都是以SELECT * FROM model 开头的。
一个GQL查询语句可以用 WHERE指定查询条件,你可以指定一个或多个条件。 和SQL不同的是,GQL查询不能包含变量值:GQL使用参数绑定查询中所有的变量.例如 , 获取当前登录用户的留言:
if users.get_current_user():
greetings = Greeting.gql("WHERE author = :1 ORDER BY date DESC",
users.get_current_user())
你也可以使用命名参数代替之:
greetings = Greeting.gql("WHERE author = :author ORDER BY date DESC",
author=users.get_current_user())
另外, Google datastore API 还提供了另外一种获取数据的方法::
greetings = Greeting.all()
greetings.filter("author =", users.get_current_user())
greetings.order("-date")
想了解 GQL查询语法的更多内容, 请查看 the Datastore reference。
清空开发版服务器中的数据存储
为了方便你测试自己的应用,GAE开发环境使用了一个临时文件来保存本地的数据,要清空本地开发环境的数据,可以使用如下的命令行:
dev_appserver.py --clear_datastore helloworld/
上一页 下一页
如果大家对于教程里的内容有疑问,或是想要参加到教程的编写工作中,欢迎访问: