如何在 Google App Engine 中更新数据

44 阅读2分钟

在创建第一个 Google App Engine 项目时,这位开发者希望为其参与的运动队创建一个简单的球员统计数据库。给定模型:

huake_00152_.jpg

class Player(db.Model):
    """ Represents a player in the club. """

    first_name = db.StringProperty()
    surname = db.StringProperty()
    gender = db.StringProperty()

他想要创建一个基本的 Web 界面来创建和修改球员信息。代码结构如下:

class PlayersPage(webapp.RequestHandler):
    def get(self):
        # Get all the current players, and store the list.
        # We need to store the list so that we can update
        # if necessary in post().
        self.shown_players = list(Player.all())

        # omitted: html-building using django template

这段代码生成了一个非常基本的 HTML 页面,其中包含一个表单和一个表格。表格中每一行对应一个球员,如下所示:

  <tr>
    <td><input type=text name="first_name0" value="Test"></td>
    <td><input type=text name="surname0" value="Guy"></td>
    <td><select name="gender0">
        <option value="Male" selected>Male</option>
        <option value="Female" >Female</option>
      </select></td>
  </tr>
  <!-- next row: first_name1, etc. -->

这位开发者希望存储自变量中的 Player 实例,以便稍后可以在其 post() 方法(同一个类)中更新玩家,方法如下:

def post(self):
    # some code skipped

    for i, player in enumerate(self.shown_players):
        fn = self.request.get('first_name'+str(i)).strip()
        sn = self.request.get('surname'+str(i)).strip()
        gd = self.request.get('gender'+str(i)).strip()
        if any([fn != player.first_name,
                sn != player.surname,
                gd != player.gender]):
            player.first_name = fn
            player.surname = sn
            player.gender = gd
            player.put()

但是,当调用 post() 方法时,self.shown_players 并不存在。估计是每次访问页面时,App Engine 都会创建一个类的实例。

他尝试了同样的想法,但将 shown_players 放到了类或模块级别(并将其调用 global),但这也不起作用。例如:

shown_players = []
class PlayersPage(webapp.RequestHandler):
    def get(self):
        # Get all the current players, and store the list.
        # We need to store the list so that we can update
        # if necessary in post().
        global shown_players
        shown_players[:] = list(Player.all())

shown_players 在 get() 中似乎有正确的值,因为 HTML 生成了正确的值,但在 post() 中为空。

  1. 解决方案

答案1:

每次请求都在处理同一个类的实例。因此,不能在 get() 中创建一个变量并在 post() 中使用其值。可以做的不是在 post() 方法中再次检索值,就是将数据存储在 memcache 中。

答案2:

在 post() 方法中,在“for”子句之前,从存储的位置检索玩家列表:

def post(self):
    # some code skipped

    self.shown_players = Player.all().fetch()
    for i, player in enumerate(self.shown_players):
      ...

答案3:

处理每个事务时应该单独对待,而不是将东西存储在全局变量中。get 请求之所以有效,是因为正在对数据库执行查询。如果想在 post 函数中更新玩家,可能想要传入详细信息,[再次查找具有这些详细信息的玩家],并根据需要修改它们。