Как сбросить тип свойства модели хранилища данных с помощью удаленного API

У меня есть модель в существующем хранилище данных. Что выглядит так:

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 для удаления устаревшего свойства, а затем сохраните объект». Но такого примера нет.

Как я могу это сделать? Мои шаги были правильными? Как удалить свойство?


person Koala Yeung    schedule 23.06.2010    source источник


Ответы (2)


Вы не можете удалить свойства из модели — каждый экземпляр модели имеет одинаковый набор свойств. Однако Expando позволяет использовать динамические свойства.

Самый простой путь, наверное, такой:

  1. Измените класс модели, чтобы расширить db.Expando вместо db.Model.
  2. Добавьте новое свойство в класс модели (используйте аргумент ключевого слова name, если вы хотите присвоить ему имя в хранилище данных, отличное от того, с которым вы обращаетесь к нему в Python) и удалите старое.
  3. Используйте API mapreduce для перебора каждого объекта, вызывая "del mymodel.oldprop" и соответствующим образом задайте новое свойство.
  4. Снова обновите определение модели, вернув его к расширению db.Model.
person Nick Johnson    schedule 23.06.2010
comment
Извиняюсь. Я обновил фрагмент сейчас. Старое поле бинарное, поэтому его трудно мигрировать. - person Koala Yeung; 23.06.2010
comment
Обновлен мой пост с более конкретными инструкциями. - person Nick Johnson; 23.06.2010

Используйте так

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

person Sallu    schedule 11.01.2012