python - 如何使用远程 API 重置数据存储模型的属性类型

标签 python google-app-engine

我在现有数据存储中有一个模型。看起来像这样:

class SomeKind(db.Model):
  name = db.StringProperty(required=True)
  someField = db.BlobProperty(required=True)

数据存储中大约有 20000 多个此类实体 现在我想重组这种类型并使其成为这样:

class SomeKind(db.Model):
  name = db.StringProperty(required=True)
  someField = db.StringProperty(required=True)

我想我必须

  1. 循环访问数据存储以删除现有的“someField”数据。来自 models.py
  2. 删除属性
  3. 将具有新定义的属性添加到 models.py

我陷入了 (1) 想要使用远程 API 删除现有属性的位置:

import sys, time, urllib2

sys.path.append("gae/paths")
...
sys.path.append("myapp/path")
from google.appengine.ext import db
from google.appengine.api import memcache
from google.appengine.ext.remote_api import remote_api_stub
from models import *

def tryPut(db, set, tryLimit=10, seconds=5, trying=1):
  try:
    db.put(set)
    return True
  except urllib2.HTTPError:
    if trying <= tryLimit:
      print "retry (%d of %d) in 5 seconds" % (trying, tryLimit)
      time.sleep(5)
      tryPut(db, set, seconds, trying+1)
    else:
      print urllib2.HTTPError
      sys.exit()

def main():

    remote_api_stub.ConfigureRemoteDatastore(None, 
      '/remote_api', my_auth_func, 'myapp.appspot.com')
    q = db.GqlQuery("SELECT * FROM SomeKind")
    last_cursor = memcache.get('SomeKind/update')

    if last_cursor:
        q.with_cursor(last_cursor)

    set = q.fetch(100)

    while len(set) != 0:
      for someKind in set:
        print someKind.name

        # this doesn't work
        delattr(someKind, "someField")

        # this doesn't work either
        del someKind.someField

      print "update to Google"
      if tryPut(db, set):
        cursor = q.cursor()
        memcache.set('SomeKind/update', cursor)

if __name__ == "__main__":
  main()

我在我的机器上运行这个。 问题是这个脚本,无论使用哪种方法,总是会引发错误:

Traceback (most recent call last):
File "./query.py", line 91, in <module>
  main()
File "./query.py", line 66, in main
  del someKind.someField
AttributeError: __delete__

文档( http://code.google.com/intl/en/appengine/articles/update_schema.html )说了类似“使用 delattr 删除过时的属性,然后保存实体”之类的内容。但从来没有这样的例子。

我该怎么做? 我的步骤正确吗? 我如何删除该属性?

最佳答案

您无法从模型中删除属性 - 每个模型实例都具有相同的一组属性。 Expando但是,允许您拥有动态属性。

最简单的路径可能是这样的:

  1. 更改模型类以扩展 db.Expando 而不是 db.Model
  2. 将新属性添加到模型类(如果您想在数据存储中为其指定与在 Python 中访问它时使用的名称不同的名称,请使用“name”关键字参数)并删除旧属性。
  3. 使用mapreduce API迭代每个实体,调用“del mymodel.oldprop”,并根据需要设置新属性。
  4. 再次更新模型定义,将其设置回扩展 db.Model。

关于python - 如何使用远程 API 重置数据存储模型的属性类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3100326/

相关文章:

php - 插件设置 WordPress 3.8.1 在 Google App-engine SDK 上运行

Python Textwrap - 强制 'hard' 中断

python - 自定义 Django 数据库前端

python - 在不创建列表的情况下以不同的顺序迭代 itertools.product

python - 短信文本解决方案

java - 在 Google App Engine 中收到 Spring RequestMappingHandlerMapping 错误

python - python 中一个 future 可以有多个服务员吗?

带循环的 Python doctest

python - WebTest:使用装饰器+数据存储调用进行测试

google-app-engine - Google App Engine - 将现有的 NDB 属性升级为重复的结构化属性