2010-06-23 9 views
2

J'ai un modèle dans un magasin de données existant. Ce qui ressemble à ceci:Comment réinitialiser le type de propriété d'un modèle de banque de données avec l'API à distance

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

Il y a environ 20000+ entités, de ce genre, dans le datastore Maintenant, je veux restructurer le genre et le rendre ainsi:

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

Je pense que je parcourir

  1. Parcourez le magasin de données pour supprimer les données "someField" existantes. de models.py
  2. Retirez la propriété
  3. Ajoutez la propriété, avec la nouvelle définition, models.py

Je suis stucked à (1) où je veux supprimer l'attribut existant avec l'API à distance:

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() 

Je l'exécute sur ma machine. Le problème est ce script, soit la méthode utilisée, soulève toujours l'erreur:

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__ 

La documentation (http://code.google.com/intl/en/appengine/articles/update_schema.html) a dit quelque chose comme « l'utilisation delattr pour supprimer la propriété obsolète et puis enregistrez l'entité ». Mais il n'y a pas d'exemple quoi que ce soit.

Comment est-ce que je peux faire ceci? Mes étapes étaient-elles correctes? Comment supprimer la propriété?

Répondre

3

Vous ne pouvez pas supprimer les propriétés d'un modèle - chaque instance de modèle a le même ensemble de propriétés. Expando, cependant, vous permet d'avoir des propriétés dynamiques.

Le chemin le plus facile est probablement ceci:

  1. Changer votre classe de modèle pour étendre db.Expando au lieu de db.Model
  2. Ajouter la nouvelle propriété à la classe modèle (utilisez l'argument mot-clé « nom » si vous voulez lui donner un nom différent dans le magasin de données à quoi vous y accédez en Python) et en retirer l'ancien.
  3. Utilisez le mapreduce API pour parcourir toutes les entités, en appelant "del mymodel.oldprop" et en définissant la nouvelle propriété en conséquence.
  4. Actualisez à nouveau la définition du modèle, en la définissant sur extension db.Model.
+0

Désolé. J'ai mis à jour l'extrait maintenant. L'ancien champ est binaire, c'est pourquoi il est difficile de migrer. –

+0

Mis à jour mon message avec des instructions plus spécifiques. –

1

Utilisez comme cette

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) 

et

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

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

Questions connexes