开发者

ListProperty of custom properties

Is there a elegant way of using a ListProperty for storing a subclassed db.Property type?

For example, the FuzzyDateProperty from this example uses get_value_for_datastore() and make_value_from_datastore() to convert its attributes into one int that is stored in the datastore. Since that one int is a Python primitive, it seems that you should be able to create a ListProperty of FuzzyDateProperty. How?

In my particular case, i've defined a class and helper functions to neatly serialize / deserialize its attributes. I would like to encapsulate the class as a db.Property, rather than make the implementer handle the relationship between the class and the Mod开发者_C百科el property.


According to the Types and Property Classes doc

The App Engine datastore supports a fixed set of value types for properties on data entities. Property classes can define new types that are converted to and from the underlying value types, and the value types can be used directly with Expando dynamic properties and ListProperty aggregate property models.

My reading of this suggests that you should be able to just specify the extended db.Property as the item_type of the for the ListProperty. But there is a logged issue that suggest otherwise.

Assuming that doesn't work, I think the next best thing is probably to subclass ListProperty and manually extend it with getters, setters, and iterators, based on the "get_value_for_datastore" and "make_value_from_datastore" functions for lists with "FuzzyDateProperty" members.


You can't do this - ListProperty expects a basic Python type, not a property class. Property classes, meanwhile, expect to be attached to a Model, not another property.


As recommended by @mjhm and @Nick, i've subclassed ListProperty to accept any class. I've uploaded a generic version to GitHub, named ObjectListProperty. I use it as a cleaner alternative to using parallel ListProperty's.

ObjectListProperty transparently serializes/deserializes when getting & putting the model. It has an internal serialization method that works for simple objects, but can handle more complex objects if they define their own serialization method. Here's a trivial example:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜