翻译:

原文:

The Django Form Validation Framework on Google App Engine

- 在Google App Engine上使用Django表单验证框架

本周热门

其它收藏服务:

Yahoo书签 QQ书签 百度搜藏 Del.icio.us Google书签 和讯网摘 天极网摘 添加到饭否 收客网

金牌译作 在Google App Engine上使用Django表单验证框架

1135个读者 翻译: firesh  06/11/2008 原文 引用 双语对照及眉批

简介

(请确保你了解HTML、Google  APP  Engine  及基本的网页知识再开始阅读此文章。)

在这篇文章告诉我们如何在Google  APP  Engine  使用Django  表格验证框架。这个框架可以让您由数据模型生成HTML表单,并且在表单和数据库进行交互时,它能准确地处理表单里的信息。

在Google App Engine上使用Django表单验证框架

原文作者:Alexander Power
翻译:Wang Shaobo

April 2008

导言

在这篇文章告诉我们如何在Google APP Engine 使用Django 表格验证框架。这个框架可以让您由数据模型生成HTML表单,并且在表单和数据库进行交互时,它能准确地处理表单里的信息。

什么是Django表单验证框架?

Django表单验证框架是Django项目的一部分。它通过数据库模型为你的应用程序构建高质量的HTML表单。它也拥有服务端功能,验证条目并将数据存入数据库中。有了Django表单框架,你能够轻松地将你地数据模型生成一套页面,这些页面可以插入、更新数据到数据库中。一旦数据存入了数据库中,你就可以使用GQL查询来访问这些数据了。

Django表单是如何与数据库进行交互的呢?

Google APP Engine 的模型(db.Model)和Django使用的模型是不一样的。所以你不能直接地在Google App Engine上使用Django表单验证框架。然而,Google App Engine有一个db.djangoforms单元,它映射着Google App Engine使用的datastore 模型和Django模型。在大多数情况下,你可以使用db.djangoforms.ModelForm的方式一样地使用Django框架。

购物清单(Shopping List) - 一个示例

我们准备使用Django表单来开发一个简单的应用。它能让你添加或者更改一个购物清单的条目,然后把信息存储到我们的数据库。左后我们可以使用GQL来查询数据,并显示到我们的应用上。

首先,我们要为我们的应用导入Python和Google App Engine所需的模块。请注意,你必须在导入任何Django模块前导入google.appengine.webapp.template:

import cgi
import wsgiref.handlers

from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp importtemplate

from google.appengine.ext.db import djangoforms

为示例定义模型和表单类

接下来,我们定义购物清单条目模型,它是Google App Engine的db.Model的子类。对于每个对象,我们记录条目的名称,数量,价格,日期和创作的用户:

class Item(db.Model):
  name
= db.StringProperty()
  quantity
= db.IntegerProperty(default=1)
  target_price
= db.FloatProperty()
  priority
= db.StringProperty(default='Medium',choices=[
   
'High','Medium','Low'])
  entry_time
= db.DateTimeProperty(auto_now_add=True)
  added_by
= db.UserProperty()

下一步,我们创建基于刚才的模型的表单对象。我们创建一个继承djangoforms.ModelFrom的类,并创建一个Meta的子类,我们在这个子类里指定模型并排除我们不想放到表单的单元。在这种情况下,因为我们可以利用Users API来获取将条目添加到购物清单的用户,我们不必要在表单里包含added_by项:

class ItemForm(djangoforms.ModelForm):
 
class Meta:
    model
=Item
    exclude
=['added_by']

我们也不必要让每个用户指定条目的添加时间。不过,当生成一个表单时,auto_now或者auto_now_add设为true的DateTime项是不会自动显示的。因此我们不必要将entry_time列入例外的列表中。

定义请求处理器(Request Handlers)

添加一个条目(Item)

现在,让我们为购物清单创建请求处理器。表单可以通过HTTP的GET请求在根URL上访问,用户通过一个HTTP的POST请求至同样的URL提交表单到我们的应用。

自动验证表单是Django先进功能之一。如果用户提交的数据不合法,Django会残生一错误信息并自动显示在消息框中,提示用户改正输入的错误。

这样定义处理HTTP GET请求的方法:

class MainPage(webapp.RequestHandler):
 
def get(self):
    self
.response.out.write('<html><body>'
                           
'<form method="POST" '
                           
'action="/">'
                           
'<table>')
   
# This generates our shopping list form and writes it in the response
    self
.response.out.write(ItemForm())
    self
.response.out.write('</table>'
                           
'<input type="submit">'
                           
'</form></body></html>')

这个表单将用我们指定的默认值预设条目,没有指定默认值的将为空。另外,如果我们设定了一个固定的选择列表,它将创建一个下拉菜单。

接下来,我们写一个用来处理HTTP POST请求的方法:

 def post(self):
    data
=ItemForm(data=self.request.POST)
   
if data.is_valid():
     
# Save the data, and redirect to the view page
      entity
= data.save(commit=False)
      entity
.added_by = users.get_current_user()
      entity
.put()
      self
.redirect('/items.html')
   
else:
     
# Reprint the form
      self
.response.out.write('<html><body>'
                             
'<form method="POST" '
                             
'action="/">'
                             
'<table>')
      self
.response.out.write(data)
      self
.response.out.write('</table>'
                             
'<input type="submit">'
                             
'</form></body></html>')

我们利用data.is_valid()来检查用户的输入是否有错误。如果有,根据用户输入的信息重新显示表单,并提示出错误信息。

如果表单的输入是合法的,data.save将会生成一个datastore实体。由于我们希望加入用户的信息到实体中,我们指定了 commit = False. 没有它,调用save()将会把实体直接存入datastore. 我们把当前用户的信息包含进去,然后调用put()函数将数据存入datastore.

注意:默认值对初始化datastore的实体是很有用的。但是,我们不能使用users.get_current_user()初始化当前用户,因为他和个值是隐含在请求之中的。Property 页面有更多的信息。

显示清单

当我们添加条目到我们的购物清单后,我们想让用户访问URL /items.html时显示出它们来。我们为这个页面创建另外一个请求处理器,它使通过使用GQL这个查询语言来查询datastore.

class ItemPage(webapp.RequestHandler):
 
def get(self):
    query
= db.GqlQuery("SELECT * FROM Item ORDER BY name")
   
for item in query:
      self
.response.out.write("%s - Need to buy %d, cost $%0.2f each<br>"%
                             
(item.name, item.quantity, item.target_price))

写我们的主函数main()

当我们写完所有的处理请求的类后,我们需要定义main()函数来处理CGI请求:

def main():
  application
= webapp.WSGIApplication(
                                       
[('/',MainPage),
                                       
('/items.html',ItemPage),
                                       
],
                                       debug
=True)
  wsgiref
.handlers.CGIHandler().run(application)

if __name__=="__main__":
  main
()

这个主函数直接将每个请求根据URL来映射到适当的请求处理函数。

写应用配置文件app.yaml

在Google App Engine上,app.yaml文件包含指定关于哪一个脚本来处理收到的请求的配置信息。我们的应用只有一个脚本,form.py,所以所有的请求都将交给那个脚本来处理:

application: shoppinglist
version
:1
runtime
: python
api_version
:1

handlers
:
- url:.*
  script
: form.py

编辑存在的实体

我们可以改进上面的示例,允许购物清单的用户编辑自己创建的条目。

修改ItemPage类

首先,当我们处理一个条目列表页面请求时,我们为每条添加一个链接,这样就可以点击然后编辑它们了。链接将请求至/edit这个地址,它包含条目的id。

class ItemPage(webapp.RequestHandler):
 
def get(self):
    query
= db.GqlQuery("SELECT * FROM Item ORDER BY name")
   
for item in query:
      self
.response.out.write('<a href="/edit?id=%d">Edit</a> - '%
                              item
.key().id())
      self
.response.out.write("%s - Need to buy %d, cost $%0.2f each<br>"%
                             
(item.name, item.quantity, item.target_price))

添加一个EditPage类

现在,我们添加一个EditPage类来处理编辑(edit)的请求。这个处理器和添加的那个类似。

在EditPage类里的get()方法中,我们首先从datastore里获得要编辑的实例,然后把它传给渲染页面,这样就装入了条目的信息了。:

class EditPage(webapp.RequestHandler):
 
def get(self):
   id =int(self.request.get('id'))
    item
=Item.get(db.Key.from_path('Item', id))

    self
.response.out.write('<html><body>'
                           
'<form method="POST" '
                           'action="/edit">'
                           
'<table>')
    self
.response.out.write(ItemForm(instance=item))
    self
.response.out.write('</table>'
                           '<input type="hidden" name="_id" value="%s">'
                           
'<input type="submit">'
                           
'</form></body></html>'% id)

接下来,沃尔玛你写一个用来处理HTTP POST请求的方法。我们从datastore中查询我们要编辑的条目,然后使用验证框架来验证Django表单编辑的信息。和之前一样,如果信息是合法的,我们将更改的信息变更到datastore中,否这我们让用户修改它们输入的信息:

 def post(self):
   id =int(self.request.get('_id'))
    item
=Item.get(db.Key.from_path('Item', id))

    data
=ItemForm(data=self.request.POST, instance=item)
   
if data.is_valid():
     
# Save the data, and redirect to the view page
      entity
= data.save(commit=False)
      entity
.added_by = users.get_current_user()
      entity
.put()
      self
.redirect('/items.html')
   
else:
     
# Reprint the form
      self
.response.out.write('<html><body>'
                             
'<form method="POST" '
                             'action="/edit">'
                             
'<table>')
      self
.response.out.write(data)
      self
.response.out.write('</table>'
                             '<input type="hidden" name="_id" value="%s">'
                             
'<input type="submit">'
                             
'</form></body></html>'% id)

修改 main() 函数

最后,我们必须将新的URL和请求处理器添加到main函数:

def main():
  application
= webapp.WSGIApplication(
                                       
[('/',MainPage),
                                       ('/edit',EditPage),
                                       
('/items.html',ItemPage),
                                       
],
                                       debug
=True)

  wsgiref
.handlers.CGIHandler().run(application)

建立Django表单的更多信息

Django表单验证框架对数据类型的验证很严格。由于它不提供客户端输入的Javascript的验证方式,所以一些数据类型,如日期、列表要使用Django表单就比较麻烦,因为用户必须按照特定的格式来输入数据。

继续阅读
  • 2006 年互联网技术发展趋势

    已经十二月了,是该回顾一下2006年互联网技术的发展状况,和展望2007年的时候了。在随后的几周,Read/WriteWeb将发表一系列深度分析2006年出现的产品和趋势的文章。同时我们会畅想一下20...

  • 被否决的Google Logo

    优胜劣汰,Google Logo也不例外。幸福的Logo是一样的,不幸的Logo各有各的不幸······

  • Facebook如何击败Myspace,Yahoo!和Google?

    Facebook如何击溃Myspace,Yahoo!和Google? 原文作者:Christopher Beam (Slate.com在线杂志专栏作家) 每个年轻人——通常刚脱稚气——必须作出一个重...

  • Google 的疯狂面试题

    几星期前,一个朋友接受了Google公司的面试,他透露了面试中的一些问题。顺便,我把从其他几个曾经面试过的人那里听来的内容也整理在一起。最大的互联网公司Google的一份面试题集,看看你是否能够回答出...

  • 聪明地使用Google的7个技巧

    我在下面编辑了一份包含7个使用Google的技巧的清单,我相信每个人都会想要知道这些.我认为这些技巧合在一起已经代表了使用Google搜索的所有技巧和方法的最高成就.虽然除此之外还有很多小技巧,但这7...

  • 三条提高gmail工作效率的可靠忠告

    如果你是个技术专家,email是必不可少的,但要完全控制所有电邮会很困难。如果你使用gmail和firefox,这里有一些技巧可以帮你如意掌控所有电邮。 第一个技巧是补救措施:把所有邮件保存在邮箱之...

  • 深究:发掘Google Reader的功能

    Google Reader 是一款功能庞大的RSS 阅读器,不过如果你没有仔细研究它的文档,那么你很可能并未充分利用它提供的功能。 今天我将通过介绍Google Reader丰富的快捷键来展示Goo...

  • Google办公室(总部)照片——世界各国的Google总部

    Google办公室(总部)——位于世界各国的照片...这是做梦都想去工作的地方呀:)

相关小组

标签:

内容有问题?请与我们联络。

译作评分

  • Currently 0.00/5
  • 1
  • 2
  • 3
  • 4
  • 5
 0.0  |  0 个评分

0条评论    0眉批

添加评论

欢迎访问译言网。在这里,您可以。。。

阅读
发现
翻译