Skip to main content
 首页 » 编程设计

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

2024年08月12日33qq78292959

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

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”数据。来自模型.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 中访问它时使用的名称不同的名称,请使用“名称”关键字参数)并删除旧属性。
  3. 使用mapreduce API迭代每个实体,调用“del mymodel.oldprop”,并根据需要设置新属性。
  4. 再次更新模型定义,将其设置回扩展 db.Model。