代码之家  ›  专栏  ›  技术社区  ›  Koala Yeung

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

  •  2
  • Koala Yeung  · 技术社区  · 16 年前

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

    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删除过时的属性,然后保存实体”。但从来没有这样的例子。

    我的步子对吗? 如何删除该属性?

    2 回复  |  直到 16 年前
        1
  •  3
  •   Nick Johnson    16 年前

    不能从模型中删除属性-每个模型实例都有相同的属性集。 Expando

    1. 将新属性添加到模型类中(如果您想在数据存储中为它指定一个与在Python中访问它的名称不同的名称,请使用'name'关键字参数),然后删除旧属性。
    2. 使用 mapreduce API 迭代每个实体,调用“del mymodel.oldprop”,并根据需要设置新属性。
    3. 再次更新模型定义,将其设置回extending db.model。
        2
  •  1
  •   Sallu    14 年前

    像这样使用

    class News(db.Expando):
        title = db.StringProperty()
        #category = db.TextProperty()    ---> removed property
        tags = db.StringProperty()
        content_short = db.TextProperty()
        content_long = db.TextProperty()
        date = db.DateTimeProperty()
        views = db.IntegerProperty(default=0)
    

    news = query.fetch(limit=PAGESIZE+1,offset=(int(page)-1)*PAGESIZE)
    for n in news:
        del n.category
        n.put()
    

    http://appengine4dummies.blogspot.com/2012/01/text-that-matters-deleting-appengine.html