用Google App Engine写一个留言板程序(一)

 

分享一下学习Google App Engine的学习心得,整个文章包括以下部分:

·Google App Engine前言介绍
·开发环境配置
·起步,写个Hello, World!进行测试
·App Engine的对象实体,使用Datastore API添加并显示留言内容
·使用Users API,创建用户登录和管理员身份识别,回复留言、删除留言
·让你的程序更健壮,捕捉处理异常和错误
·激动人心的地方,使用模板!
·如何在程序中使用静态文件,如CSS、脚本、图片、视频等。
·将程序上传到Google App Engine的免费测试服务器http://application-id.appspot.com

这是文章的第一部分

前言:什么是Google App Engine?
    Google App Engine是一个托管的服务,允许你本地使用Google基础设施构建Web应用,待其完工之后再将其部署到Google基础设施之上(Google的服务器环境)。Google App Engine分为免费版和收费版,免费版提供了一个配额系统,它限制了应用免费可用的存储、CPU和带宽。目前免费版的配额包括:3个应用/开发者、500MB存储/应用、2000封邮件/天(连续24小时)、10 GB入站带宽、10 GB出站带宽、200M CPU兆周、650k HTTP请求、2.5M Datastore API调用和160k URL Fetch API调用。这对我们来说足可以创建一个小型的、学习试验目的程序了。
    目前Google App Engine提供的语言支持仅为Python,未来可能会增加更多语言支持(估计短期不太可能)。
Google App Engine SDK可以看作是类似.NET Framework一样的平台(这个比喻不太恰当,但你可以先这样理解),这个环境运行在Google的服务器上,Google对它的安全、性能等作了多种限制和调节。另外Google App Engine是有选择性的支持Python,你不可能用到Python的全部特性。

关于Google App Engine的更多信息可以了解Google推出Web开发利器:AppEngine


开发环境配置(本文描述的系统环境为windows系统):

1、Google App Engine是运行在Python2.5基础上的,如果没有安装Python 2.5,请从Python的官方网站(http://www.python.org/)下载和安装对应操作系统的版本。
2、下载App Engine SDK(http://code.google.com/appengine/downloads.html)。截至写文章之前,SDK的最新版本是1.1,下载后运行安装程序,按照提示操作即可。
3、有两个重要的命令帮助我们处理操作程序
·dev_appserver.py,Web服务器开发
(http://code.google.com/appengine/docs/thedevwebserver.html)
·appcfg.py,用来上传你的程序到App Engine
(http://code.google.com/appengine/docs/appcfgpy.html)
正常安装SDK,Windows安装程序会把这些命令直接放到命令路径中。安装完成SDK之后,你可以直接从命令行窗口下运行这些命令。


起步,写个Hello, World!进行测试

1、创建一个名为helloworld的目录。本程序提到的所有文件都放置在这个目录中。
进入到helloworld目录中,创建一个名为helloworld.py的文本文件,并添加以下代码:

# -*- coding: utf-8 -*-
print 'Content-Type: text/plain'
print ''
print 'Hello, world!'

这个Python脚本响应一个请求,这个响应包括描述内容类型的HTTP头、一个空行
以及信息“Hello world!”。

2、创建配置文件
App Engine应用程序有一个名为app.yaml的配置文件。此文件描述了哪个处理器(handler)脚本对应哪个URL。在helloworld目录中,创建一个名为app.yaml的文件,并添加以下内容:

application: helloworld
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: helloworld.py

这个文件的语法是YAML(http://www.yaml.org/)。若要查看完整的配置选项列表,请查看app.yaml参考(http://code.google.com/appengine/docs/configuringanapp.html)。
可以把这个文件当成asp.net的web.config文件,主要配置程序一些必要的信息。

3、测试
    在桌面点击开始->附件->命令提示符,在命令提示符状态下进入使用下列命令启动Web服务器,路径为helloworld的目录:
dev_appserver.py helloworld/
    注意:是目录外,而且目录名不能包含空格
    正常情况下,这个Web服务器开始运行,可以监听8080端口的请求。通过在浏览器中访问下面的地址来测试这个程序。http://localhost:8080/,如果一切正常,浏览器中会显示出Hello world!的字样。你可以编辑helloworld.py文件,将Hello, world!替换成其它字符,刷新浏览器即可看到变化。若要关闭Web服务器,在终端窗口激活的情况下,按下Control-C(或Control-Break)。或者直接关掉窗口。


接下来我们开始实现写一个留言板程序

1、创建一个目录,名字为messageboard,创建一个app.yaml文件,添加以下内容:

application: messageboard
version: 1
runtime: python
api_version: 1

handlers:
- url: /
  script: messageboard.py


2、创建一个messageboard.py,添加以下内容:

# -*- coding: utf-8 -*-

import os
import re
import cgi
import datetime
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template

   
    # -*- coding: utf-8 -*-是告诉python,这个文件格式为utf-8(保存文件时也要选择保存为utf-8),import语句相当于asp.net 的using,将需要的类库导入到程序中,其中以google.*开头的是Google App Engine SDK里面的库。具体import和from的区别可参考python的文档。

3、继续,创建一个实体类,将以下代码添加至messageboard.py

class Message(db.Model):
    title
=db.StringProperty()
    nickname
=db.StringProperty()
    email
=db.EmailProperty()
    website
=db.LinkProperty()
    content
=db.StringProperty(multiline=True)
    reply
=db.StringProperty(multiline=True)
    ipaddress
=db.StringProperty()
    adddate
=db.DateTimeProperty(auto_now_add=True)

   
    这个类定义了一个留言信息的Model,诸如留言标题、昵称、电子邮件等属性,其中的db.StringProperty()之类的代码是指定了属性的数据类型,db.StringProperty()代表这个属性是个字符串,db.StringProperty(multiline=True)是一个带有multiline=True参数的db.StringProperty类型,指定属性可以存储多行文本。db.EmailProperty()和db.LinkProperty()是SDK为我们定义好的属性类型,指定属性必须为Email格式和超链接格式,带有auto_now_add=True参数的db.DateTimeProperty类型指定了当对象被创建时,如果应用程序没有赋予其他值,那么新的对象自动被赋予一个date的时间。更多的信息可以参考(http://code.google.com/appengine/docs/datastore/typesandpropertyclasses.html

4、实现添加留言的功能,将以下代码添加至messageboard.py:

class MainPage(webapp.RequestHandler):
    
def get(self):        
        self.response.out.write(
"""
          <form action="/sign" method="post">
          <div><input type="text" name="title"/></div>
            <div><input type="text" name="nickname"/></div>
            <div><input type="text" name="email"/></div>
            <div><input type="text" name="website"/></div>
            <div><textarea name="content" rows="3" cols="60"></textarea></div>
            <div><input type="submit" value="Sign Guestbook"></div>
          </form>
        </body>
      </html>
""")
        
class Add(webapp.RequestHandler):
    
def post(self):
        message 
= Message()
        message.title 
= self.request.get('title')
        message.nickname 
= self.request.get('nickname')
        message.email 
= self.request.get('email')
        message.website 
= self.request.get('website')
        message.content 
= self.request.get('content')
        message.put()
        self.redirect(
'/')
              
def main():
    application 
= webapp.WSGIApplication([('/', MainPage),('/sign', Add)],debug=True)
    wsgiref.handlers.CGIHandler().run(application)
        
if __name__ == "__main__":
    main()

    这次添加的代码稍多一些,主要是两个类,一个是MainPage用来显示留言的表单,程序是直接将硬代码write到页面了;Add类用来将提交的表单存储到数据库中。message.put()的作用就是保存我们的Message对象到数据库中,并转向到起始页。
    还有一个函数main用来接受请求并指定请求匹配的处理器(这里指的就是MainPage类和Add类),例如,当webapp接收到一个HTTP GET对URL“/”的请求时,它会实例化MainPage类,并调用这个实例的get方法。参数debug=true可以捕捉错误或异常并且显示出来。
    应用程序本身由webapp.WSGIApplication实例来呈现,代码使用了来自Python标准库的wsgiref模块来运行WSGIApplication,即一个CGI适应器。想要了解这个模块更多的信息,请访问wsgiref模块文档(http://docs.python.org/lib/module-wsgiref.html)。了解webapp的更多信息,请查看webapp参考(http://code.google.com/appengine/docs/webapp/)。

5、接下来我们再修改一下app.yaml文件

application: messageboard
version: 1
runtime: python
api_version: 1

handlers:
- url: /
  script: messageboard.py

- url: /add
  script: messageboard.py

    现在就可以运行dev_appserver.py messageboard/ 进行调试了。在浏览器中输入http://localhost:8080/,可以看到留言表单,输入一些内容测试。点击提交按钮并没有出现什么变化,实际上数据已经存储了。开发Web服务器使用一个本地版本的数据库来测试你的应用程序,即使用临时文件。只要临时文件错在数据就会一直存在,Web服务器不会重置这些文件
    除非你要求这么做。如果你想要开发服务器在启动时预先清除数据库,请在启动服务器时添加--clear_datastore选项:
dev_appserver.py --clear_datastore messageboard

6、那么,如何将存储的数据显示出来呢?修改你的MainPage类如下:

class MainPage(webapp.RequestHandler):
    
def get(self):
        messages 
= db.GqlQuery("SELECT * FROM Message ORDER BY adddate DESC LIMIT 10")
        
for message in messages:          
            self.response.out.write(
'%s于%s留言:'%(message.nickname,message.adddate))
            self.response.out.write(
'<hr/>邮件:%s<br/>网址:%s<br/>留言内容:<blockquote>%s</blockquote>' %(message.email,message.website,cgi.escape(message.content)))
        self.response.out.write(
"""
          <form action="/add" method="post">
          <div>标题:<input type="text" name="title"/></div>
            <div>昵称:<input type="text" name="nickname"/></div>
            <div>邮件:<input type="text" name="email"/></div>
            <div>网址:<input type="text" name="website"/></div>
            <div>内容:<textarea name="content" rows="3" cols="60"></textarea></div>
            <div><input type="submit" value="提交"></div>
          </form>
        </body>
      </html>
""")

    看看这句messages = db.GqlQuery("SELECT * FROM Message ORDER BY adddate DESC LIMIT 10"),Google App Engine使用与sql语句相似的称为gql的语句进行数据库查询,这个查询返回添加的信息的Message对象模型。接下来
for message in messages:         
            self.response.out.write('%s于%s留言:'%(message.nickname,message.adddate))
            self.response.out.write('<hr/>邮件:%s<br/>网址:%s<br/>留言内容:<blockquote>%s</blockquote>' %(message.email,message.website,cgi.escape(message.content)))
用于遍历这个messages对象集合,并将内容write出来。。
    GQL和SQL相似度较高,其中GQL增加了一些特殊语法,已适应App Engine的环境,查看完整的GQL及查询API描述,请参见数据存储参考(http://code.google.com/appengine/docs/datastore/)。

    调试一下我们的程序,如果测试服务器没有关闭的话,刷新一下浏览器中(http://localhost:8080/)即可看到刚刚提交的留言,你可以尝试继续提交留言并查看变化。
    注意,当填写的Email和Url不符合标准的话,测试服务器会捕捉到错误并显示出来,例如:BadValueError: Invalid URL: ww.124.cm 说明添加的网址格式错误,我们可以根据此机制来编写处理代码,让我们的程序更健壮、更安全。

    通过以上的学习,初步构建了一个可以运行在本地App Engine环境的程序,当然,它还很稚嫩,程序不健壮、界面不友好,没有区分用户身份,无法对存储数据管理等等。下篇文章将帮你解决这些问题,下篇文章预告:

  • ·使用Users API,创建用户登录和管理员身份识别,回复留言、删除留言
    ·让你的程序更健壮,捕捉处理异常和错误
    ·激动人心的地方,使用模板!
    ·如何在程序中使用静态文件,如CSS、脚本、图片、视频等。
    ·将程序上传到Google App Engine的免费测试服务器http://application-id.appspot.com

 完整代码下载

posted @ 2008-06-24 15:49 红尘中迷茫 阅读(2555) 评论(21)  编辑 收藏 所属分类: pythonGoogle App Engine

  回复  引用  查看    
#1楼 [楼主]2008-06-24 15:52 | 红尘中迷茫      
第一次发,排版不太好。。
  回复  引用  查看    
#2楼 2008-06-24 16:06 | xjb      
嗯,不错,支持一下,我很看好gg的这个应用,等于是提供虚拟主机给开发者,开发者只要关心应用就可以了,不必再费心关心什么网络呀,服务器呀。

不过,我有些担心,说不好gae会怕被gfw给封了。
  回复  引用  查看    
#3楼 2008-06-24 16:18 | 探索之鸟      
google的又一个经典服务..
  回复  引用  查看    
#4楼 [楼主]2008-06-24 16:29 | 红尘中迷茫      
这个服务确实很不错,不过限制也很多,可以说学习是够用了,可惜程序语言只支持python,虽然google说会支持其他语言,不知道要等到何年了。
  回复  引用  查看    
#5楼 2008-06-24 16:36 | 暗香浮动      
真的很有意思的一个应用。
关键是免费的资源啊
可惜还没有学过python
  回复  引用  查看    
#6楼 2008-06-24 16:45 | BAsil      
不错,赞一个
  回复  引用  查看    
#7楼 2008-06-24 16:46 | yushih      
gae迟早被封
  回复  引用  查看    
#8楼 2008-06-24 16:54 | 暗香浮动      
呵呵,被和谐了再说么。现在感觉还不错么。
  回复  引用  查看    
#9楼 2008-06-24 17:12 | 暗香浮动      
google app engine的示例程序类似么
  回复  引用    
#10楼 2008-06-24 17:13 | w3r [未注册用户]
可以绑定域名吗?
  回复  引用  查看    
#11楼 2008-06-24 17:16 | Indigo Dai      
Google在拥抱开发人员,而且都是基于WEB的。
  回复  引用  查看    
#12楼 2008-06-24 17:25 | 梁逸晨      
现在似乎已经不能注册了,我连续几天都试了很多手机,都没有收到验证码
  回复  引用  查看    
#13楼 [楼主]2008-06-24 17:38 | 红尘中迷茫      
@暗香浮动
在那个示例的基础上编写的,增加了很多示例没有提到的东西,而且GAE程序基本相通,学会写留言板后,其它的程序就容易了,具体的在下篇。

@w3r
可以绑定域名
http://code.google.com/appengine/articles/domains.html

@Indigo Dai
我看Google需要new ideas

@梁逸晨
不会吧,是+86 手机号的格式吗?
  回复  引用    
#14楼 2008-06-24 17:55 | h-lei [未注册用户]
@梁逸晨
我也收不到验证码,不知道怎么回事
  回复  引用  查看    
#15楼 2008-06-24 18:03 | jjx      
俺写了个blog
http://soho-works.appspot.com/blog/ 用的是django 其实也有了个guestbook的,不过gae中的django app定位模板好像有问题
都把域名 www.soho-works.net 转过去了,没想到二天后就gfw 了,所以,暂时不去搞他了
  回复  引用  查看    
#16楼 2008-06-24 18:12 | U2U      
Google这个东西没有任何实用价值
  回复  引用    
#17楼 2008-06-24 22:10 | 净化工作台 [未注册用户]
飙风引擎engine。
  回复  引用  查看    
#18楼 2008-06-25 09:38 | MK2      
--引用--------------------------------------------------
xjb: 嗯,不错,支持一下,我很看好gg的这个应用,等于是提供虚拟主机给开发者,开发者只要关心应用就可以了,不必再费心关心什么网络呀,服务器呀。

不过,我有些担心,说不好gae会怕被gfw给封了。
--------------------------------------------------------
很有可能会被封啊。。。。
  回复  引用    
#19楼 2008-06-27 09:54 | sdfef [未注册用户]
佛山网球培训,佛山网球培训班,佛山网球教练,佛山网球俱乐部,佛山网球场,佛山网球佛山康之杰体育电话:0757-86180305 qq:562550810详情请登录http://www.sporter.org.cn/zhusanjiao/佛山网球培训,佛山网球培训班,佛山网球教练,佛山网球俱乐部,佛山网球场,佛山网球


  回复  引用  查看    
#20楼 2008-07-03 10:26 | 数据绑定者      
python不错的,django也不错
  回复  引用    
#21楼 2008-07-17 10:45 | niu [未注册用户]

--引用--------------------------------------------------
h-lei: @梁逸晨
我也收不到验证码,不知道怎么回事
--------------------------------------------------------

用联通的就可以了,移动的收不到~~
我也是叫朋友帮我收的~~

http://www.google.com/support/calendar/bin/answer.py?answer=37226&hl=en#C

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  博客园首页

  新闻频道

  社区

  小组

  博问

  网摘

  闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-06-24 15:58 编辑过
成果网帮您增加网站收入


相关链接: