Log in

Google App Engine 入门:数据存储

May 10th, 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 入门:数据存储”共有8个评论

  1. Google App Engine 入门 :处理表单数据 | 徐明的博客 说:

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

  2. 江勇 说:

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

  3. 江勇 说:

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

  4. Nowings 说:

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

  5. 江勇 说:

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

    帮忙看看?

  6. 江勇 说:

    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

  7. 江勇 说:

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

  8. simon hsu 说:

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

我要留言

订阅

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