Change IntegerProperty to FloatProperty of existing AppEngine DataStore

别等时光非礼了梦想. 提交于 2019-12-19 03:16:18

问题


I built an appengine application (python) which need to convert existing datastore entities in integer value (100) to float value (100.00) for currency conversion issue. How's the right way doing this? Since my query returning error when i just change property type in my model.

Old Model:

class Learn(search.SearchableModel):
    pid = db.ReferenceProperty(Product, collection_name='picks')
    title = db.StringProperty()
    description = db.TextProperty()
    order = db.IntegerProperty()
    cost = db.IntegerProperty(default=0)
    cost1 = db.IntegerProperty(default=0)

New Model:

class Learn(search.SearchableModel):
    pid = db.ReferenceProperty(Product, collection_name='picks')
    title = db.StringProperty()
    description = db.TextProperty()
    order = db.IntegerProperty()
    cost = db.FloatProperty(default=0.000)
    cost1 = db.FloatProperty(default=0.000)

I need a proper way to alter this datastore property type without changing (delete old and add new) existing data. Since it's key used in many others table/model.

Thanks.


回答1:


The easiest way to do this is to change the model to inherit from db.Expando, and delete the integer properties from the definion. Then, load each instance and do "instance.foo = float(instance.foo)" on each, before saving them back to the datastore - you'll probably want to use the mapreduce API for this. Finally, make the model extend db.Model again, and add the FloatProperties back.

You really, really don't want to use a float for currency, though: floats are susceptible to rounding errors, which means you can lose (or gain!) money. Instead, use an IntegerProperty that counts the number of cents.




回答2:


Here is exampe for Nick Johnson's answer:

Before:

class Person(db.Model):
    name = db.StringProperty()
    age = db.StringProperty() #this will go to int

After

class Person(db.Expando):
    pass

for person in Person.all():
    person.age = int(person.age)
    person.put()

Very after:

class Person(db.Model):
    name = db.StringProperty()
    age = db.IntegerProperty() 



回答3:


Maybe a good way is to temporary create a new model:

class LearnTemp(search.SearchableModel):
    pid = db.ReferenceProperty(Product, collection_name='picks')
    title = db.StringProperty()
    description = db.TextProperty()
    order = db.IntegerProperty()
    order = db.IntegerProperty()
    cost = db.FloatProperty(default=0.000)
    cost1 = db.FloatProperty(default=0.000)

Then write some script, task or view which convert instances from old model to temporary model, converting the integer values to float. Make sure copying the id's and key's as well if somehow possible.

After change your main model and copy all entries from the temporary one to it. Then remove the temporary model.

This is most likely not the optimal way and requires some manual migration, though without South and on app engine I don't really see a good way to do it.




回答4:


From the Edit Entity page in the data store admin interface:

Enter information for the entity below. If you'd like to change a property's type, set it to Null, save the entity, edit the entity again, and change the type



来源:https://stackoverflow.com/questions/4742875/change-integerproperty-to-floatproperty-of-existing-appengine-datastore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!