正在加载...

Google App Engine 入门:数据存储

五月 11th, 2008

数据存储是个复杂的问题。用户可能在一个特定的时间发出了一个数据请求,但是下一个时间又发出了另外一个完全不同的数据请求。所有的WEB服务都需要协调这些相互影响的请求,并且这些请求可能来自世界的各个地方。

感谢Google App Engine,您再也不需要为这些发愁了。Google App Engine架构将为您处理所有关于数据分发,负载平衡的问题,并且提供了API来实现所有关于数据存储的问题。

存储已经提交的留言

App Engine 包含了一个基于Python的数据存储模型. 这个模型类似于 Django's data modelling API, 但是使用了Google自己的存储环境.

对于上一章实现的留言程序,我们想要把用户提交的留言保存起来,每个留言都包含作者名称,消息内容,发布时间等等,并且按照留言的先后将其显示出来。

编辑 helloworld/helloworld.py, 在顶部添加 import代码 :

from google.appengine.ext import db


添加 Greeting类:

class Greeting(db.Model):
author
= db.UserProperty()
content
= db.StringProperty(multiline=True)
date
= db.DateTimeProperty(auto_now_add=True)

上面的代码定义了一个数据模型类Greeting,这个类包含三个属性: author -User object类型, content - 字符串类型, date -日期类型.

其中一些属性包含了默认值:比如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 处理过程创建了一个Greeting 对象,设置了它的属性,然后使用 greeting.put()方法把它保存了起来。如果对象已经存在,使用put()方法,将会更新原先已经存在的数据。在这段代码里,我们是直接创建了Greeting对象,所以put()方法将把一个新的Greeting对象保存起来。

通过GQL查询数据

App Engine datastore 使用了一套复杂的数据储存系统.但是它并不是一个标准的关系数据库,所以不能使用标准的Sql语句进行查询。作为一个替代,Google准备了一套类Sql的查询语句,称之为GQL.GQL 提供了和SQL基本类似的语法来读取数据.

编辑MainPage :

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

刷新http://localhost:8080/ , 您可以提交一个留言看一下效果.

以下是相关的查询语句:

    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/

接下来...

现在我们已经创建一个一个完整的留言板,但是这个版本中的HTML代码都包含在MainPage处理过程中,如果我们想要修改一下WEB应用的外观,将是一件麻烦的事情,接下来我们将学习如何使用模板,添加图片,CSS等静态文件。
下一章 使用模板.

相关阅读:



“Google App Engine 入门:数据存储” 共有9条留言

  • leg On

    to 3楼:
    从英文原始文档copy代码应该不会出现问题,http://code.google.com/appengine/docs/python/gettingstarted/usingdatastore.html,
    在我的环境下没有出现任何问题

  • simon hsu On

    好像第一次访问的时候会有这个问题,可能是datastore还没有创建好,刷新一下就好了。

  • 江勇 On

    http://localhost:8080/ 可以用,但是appspot.com不能用

  • 江勇 On

    Traceback (most recent call last): File "/base/python_lib/versions/1/google/appengine/ext/webapp/__init__.py", line 499, in __call__ handler.get(*groups) File "/base/data/home/apps/kin/1.14/kin.py", line 28, in get for greeting in greetings: File "/base/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 1247, in __iter__ return self.run() File "/base/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 1558, in run query_run = self._proto_query.Run(*self._args, **self._kwds) File "/base/python_lib/versions/1/google/appengine/ext/gql/__init__.py", line 441, in Run res = bind_results.Get(self.__limit, offset) File "/base/python_lib/versions/1/google/appengine/api/datastore.py", line 928, in Get return self._Run(limit, offset)._Next(limit) File "/base/python_lib/versions/1/google/appengine/api/datastore.py", line 877, in _Run str(exc) + '\nThis query needs this index:\n' + yaml) NeedIndexError: no matching index found This query needs this index: - kind: Greeting properties: - name: date direction: desc

  • 江勇 On

    import cgi import wsgiref.handlers from google.appengine.api import users from google.appengine.ext import webapp 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('') greetings = Greeting.gql("ORDER BY date DESC LIMIT 10") for greeting in greetings: if greeting.author: self.response.out.write('%s wrote:' % greeting.author.nickname()) else: self.response.out.write('An anonymous person wrote:') self.response.out.write('

    %s
    ' % cgi.escape(greeting.content)) # Write the submission form and the footer of the page self.response.out.write(""" """) 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('/') def main(): application = webapp.WSGIApplication( [('/', MainPage), ('/sign', Guestbook)], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == "__main__": main() 帮忙看看?

  • Nowings On

    回楼上,需要严格的缩进。

  • 江勇 On

    使用数据存储和使用模板这两节的代码有问题,我调试不过。能不能把你这两节的代码发给我?谢谢 我的email:yongjiang@163.com

  • 江勇 On

    使用数据存储和使用模板这两节的代码有问题,我调试不过。能不能把你这两节的代码发给我?谢谢

  • Google App Engine 入门 :处理表单数据 | 徐明的博客 On

    [...] 下一章 使用数据存储. [...]

我要留言


google reader 抓虾
bloglines my yahoo
哪吒 鲜果
* 更多订阅本站方式请看 订阅帮助