views:

45

answers:

3

hy I need to add a property to a model that can reference 4 different models:

class WorldObject(db.Model):
    # type can only accept: text, image, profile, position
    # this should be like a set property in relational database and not a string
    type = db.StringProperty(required = True)

    # ???: this can be a reference to Profile, Image, Position or Text model
    # how to do it?
    reference = db.ReferenceProperty(reference_class = ???, required = True)

thanks


@Nick Johnson:

Here is how I've done with your help:

class WorldObject(db.Model):
# x, y: position in the world
x = db.IntegerProperty(required = True)
y = db.IntegerProperty(required = True)

# world: reference to the world containing it
world = db.ReferenceProperty(reference_class = World)

# profile: is the owner of the object and is the only one who can make changes to it's world object property
owner = db.ReferenceProperty(reference_class = Profile, required = False)

# history
updated = db.DateTimeProperty(auto_now_add = True)
created = db.DateTimeProperty(required = True)

then:

class ImageWO(WorldObject):
image = db.ReferenceProperty(reference_class = Image, required = False)

then:

class PositionWO(WorldObject):
position = db.ReferenceProperty(reference_class = Position, required = False)

and the other classes are the same.. Now if I want to get all the world objects in an area how do I do? I have to do 1 request for every class that extends world_object?

+1  A: 

According to the documentation on ReferenceProperty, you could just set reference_class to None (or not specify it, as None is the default):

reference_class is the model class of the model instance being referenced. If specified, only model instances of the class can be assigned to this property. If None, any model instance can be the value of this property.

Saxon Druce
+2  A: 

Make Profile, Image, Position and Text all extend the same base class, which itself extends Model. Then, specify that base class as the target for the ReferenceProperty. There's no need to store a separate 'type' in a StringProperty - this will be reflected in the key stored for the reference property.

Nick Johnson
I've done like this:main class:class WorldObject(db.Model): x = db.IntegerProperty(required = True) y = db.IntegerProperty(required = True) owner = db.ReferenceProperty(reference_class = Profile, required = False) updated = db.DateTimeProperty(auto_now_add = True) created = db.DateTimeProperty(required = True)then:class ImageWO(WorldObject): image = db.ReferenceProperty(reference_class = Image, required = False)class PositionWO(WorldObject): position = db.ReferenceProperty(reference_class = Position, required = False)Is that right? or I'm missing something?
Totty
That looks reasonable, insofar as I can parse it.
Nick Johnson
Sorry for the waiting time. And now may I request all the world objects in a defined area with a single request or i have to select all profiles, then all images, then all positions, then all texts in the defined area? If yes, how do i do it? thanks
Totty
+1  A: 

You can also use:

references = db.ListProperty(db.Key)

to store a list of keys to the different entities. This gives you more flexibility, as you can store keys of entities of any kind.

You can then create a convenience method that fetches the properties for you from the datastore:

def get_references(self):
    return db.get(self.references)
mahmoud