I have a Model in an existing Datastore. Which looks like this:
class SomeKind(db.Model):
name = db.StringProperty(required=True)
someField = db.BlobProperty(required=True)
There are about 20000+ entities, of this kind, in the datastore Now I want to restructure the kind and make it this way:
class SomeKind(db.Model):
name = db.StringProperty(required=True)
someField = db.StringProperty(required=True)
I think I have to
- Cycle through the datastore to remove existing "someField" data. from models.py
- Remove the property
- Add the property, with new definition, to models.py
I'm stucked at (1) where I want to delete existing attribute with remote 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()
I run this on my machine. The problem is this script, with either method, always raises error:
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__
The documentation ( http://code.google.com/intl/en/appengine/articles/update_schema.html ) said something like "us开发者_Go百科e delattr to delete the obsolete property and then save the entity". But there is no example what so ever.
How can I do this? Was my steps correct? How am I to delete the property?
You can't delete properties from a Model - every model instance has the same set of properties. Expando, however, allows you to have dynamic properties.
The easiest path is probably this:
- Change your model class to extend db.Expando instead of db.Model
- Add the new property to the model class (use the 'name' keyword argument if you want to give it a different name in the datastore to what you access it with in Python) and remove the old one.
- Use the mapreduce API to iterate over every entity, calling "del mymodel.oldprop", and setting the new property as appropriate.
- Update the model definition again, setting it back to extending db.Model.
Use like this
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)
and
news = query.fetch(limit=PAGESIZE+1,offset=(int(page)-1)*PAGESIZE)
for n in news:
del n.category
n.put()
full code here - http://appengine4dummies.blogspot.com/2012/01/text-that-matters-deleting-appengine.html
精彩评论