将现有AppEngine DataStore的IntegerProperty更改为FloatProperty

5 投票
4 回答
3202 浏览
提问于 2025-04-16 10:17

我创建了一个应用程序(用Python写的),需要把现有的数据存储中的整数值(比如100)转换成浮点值(比如100.00),这是为了处理货币转换的问题。请问该怎么做比较好?因为当我在模型中直接更改属性类型时,查询就会出错。

旧模型:

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)

新模型:

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)

我需要一个合适的方法来修改这个数据存储的属性类型,而不想删除旧的数据再添加新数据,因为这个键在很多其他表或模型中都在使用。

谢谢。

4 个回答

0

也许一个好办法是暂时创建一个新的模型:

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)

然后写一些脚本、任务或者视图,把旧模型中的实例转换到这个临时模型里,把整数值转换成浮点数。如果可能的话,确保也复制ID和键。

在修改你的主模型后,把所有条目从临时模型复制到主模型里。然后删除这个临时模型。

这可能不是最优的办法,需要一些手动迁移,不过在没有South和在应用引擎上,我实在想不到更好的方法了。

7

这里是 Nick Johnson 的一个 回答 的例子:

之前:

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

之后

class Person(db.Expando):
    pass

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

非常之后:

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

最简单的方法是把模型改成从 db.Expando 继承,然后把定义中的整数属性删掉。接着,加载每个实例,然后对每个实例执行 "instance.foo = float(instance.foo)",在保存回数据存储之前,你可能想用 mapreduce API 来处理这个。最后,再把模型改回继承 db.Model,并把 FloatProperties 加回来。

不过,真的不建议用浮点数来表示货币,因为浮点数容易出现四舍五入的错误,这样可能会导致你损失(或者多出!)钱。更好的做法是用 IntegerProperty 来表示金额,计算的是美分的数量。

撰写回答