ListProperty自定义属性

时间:2010-11-19 02:21:24

标签: python google-app-engine google-cloud-datastore

是否有使用ListProperty存储子类db.Property类型的优雅方式?

例如,来自this exampleFuzzyDateProperty使用get_value_for_datastore()make_value_from_datastore()将其属性转换为存储在数据存储区中的一个int。由于那个int是一个Python原语,您似乎应该能够创建一个ListProperty FuzzyDateProperty。怎么样?

在我的特定情况下,我已经定义了一个类和辅助函数来整齐地序列化/反序列化它的属性。我想将类封装为db.Property,而不是让实现者处理类和Model属性之间的关系。

3 个答案:

答案 0 :(得分:2)

根据Types and Property Classes doc

  

App Engine数据存储区支持a   固定的值类型集   数据实体的属性。属性   类可以定义新的类型   转换为底层证券   值类型和值类型可以   直接与Expando动态一起使用   属性和 ListProperty 聚合   物业模型。

我对此的解读表明您应该能够将扩展的db.Property指定为ListProperty的item_type。但是有一个logged issue暗示了其他原因。

假设这不起作用,我认为下一个最好的事情可能是继承ListProperty并使用getter,setter和iterators手动扩展它,基于“get_value_for_datastore”和“make_value_from_datastore”函数用于具有“FuzzyDateProperty”的列表成员。

答案 1 :(得分:1)

你不能这样做 - ListProperty需要一个基本的Python类型,而不是属性类。同时,属性类期望附加到模型,而不是另一个属性。

答案 2 :(得分:1)

根据@mjhm和@Nick的建议,我已经将ListProperty子类化为接受任何类。我uploaded a generic version to GitHub,名为ObjectListProperty。我使用它作为使用并行ListProperty的更清洁的替代方法。

ObjectListProperty在获取& amp;时透明地序列化/反序列化把模型。它有一个适用于简单对象的内部序列化方法,但如果它们定义了自己的序列化方法,则可以处理更复杂的对象。这是一个简单的例子:

from object_list_property import ObjectListProperty

class Animal():
    """ A simple object that we want to store with our model """
    def __init__(self, species, sex):
        self.species = species
        self.sex = sex if sex == 'male' or sex == 'female' else 'unknown'

class Zoo(db.Model):
    """ Our model contains of list of Animal's """
    mammals = ObjectListProperty(Animal, indexed=False)

class AddMammalToZoo(webapp.RequestHandler):
    def post(self):
        # Implicit in get is deserializing the ObjectListProperty items
        zoo = Zoo.all().get()

        animal = Animal(species=self.request.get('species'),
                        sex=self.request.get('sex') )

        # We can use our ObjectListProperty just like a list of object's
        zoo.mammals.append(animal)

        # Implicit in put is serializing the ObjectListProperty items
        zoo.put()