RHSeeger
RHSeeger

Reputation: 16262

GAE Models: How to list child nodes in parent

Using Google App Engine in Python and references, you automatically get a back reference from the referenced object to the one you're dealing with. This is described very well in the answer found here.

What I'd like to do is create a (simpler) one-to-many relationship, with each Group having a list of Tags, and each Tag belongs to only one Group. I picture it something like the following:

class Group(db.Model):
    # All of my group-specific data here.

class Tag(db.Model):
    text = db.StringProperty(required=True)
    group = db.ReferenceProperty(Group, collection='tags')

Assuming I understand everything correctly... In the above, you wind up with each Group having a tags property:

# Get the list of Tag objects that belong to a Group object
mytags = mygroup.tags 

My question is, is there a "standard" way to include that information in the Group object? When looking at the data models, you can't see by looking at the Group object that it has a list of Tags that apply to it. I'd like to be able to define Group,Tags as something like

class Group(db.Model):
    # This should automatically be the same as the "tags" property that is
    # created for the Group model by the definition of the Tag model
    tags = db.ListProperty(db.Key)
    # All of my group-specific data here.

class Tag(db.Model):
    text = db.StringProperty(required=True)
    group = db.ReferenceProperty(Group, collection='tags', required=True)
    # Other tag specific information here (such as url, etc)

The idea being that I want to be able to see, when I look at the Group model, that it has a list of Tag objects as a property. It feels unnatural to me to have to look at the Tag model to know this information.

Note: It may be worth noting that I plan on having the Group in question be the parent (for the Entity Group) of each of it's Tags. Any time I modify a Group, I will be updating it completely, replacing all of it's Tags with new ones, and I want to get the correct list of them for the given "version" of the Group I'm looking at.

The use cases for my data include:

Upvotes: 2

Views: 324

Answers (3)

Abdul Kader
Abdul Kader

Reputation: 5842

modeling in appengine

one-to-many using parent in that will come in handy for you

you can also consider other examples

Upvotes: 0

Nick Johnson
Nick Johnson

Reputation: 101149

Having a ListProperty as you suggest will, as you probably realize, mean you're keeping two references redundantly, which isn't necessary. A simpler approach would be to simply note in a comment that describes the relationship.

If you're going to use entity groups anyway, though, you don't need the ReferenceProperty or the ListProperty. You can fetch the Tag children of a Group with Tag.all().ancestor(my_group).

Another option would be to store the tags as a list of strings. Additional information can be stored in Tag entities with key_names set to the tag name. You can then fetch all the tag entities referenced by an object with Tag.get_by_key_name(my_entity.tags). This is mostly useful if you usually only need the tag names and only sometimes retrieve the full data - otherwise you may as well stick with a ReferenceProperty or an Entity Group.

Upvotes: 1

Robert Kluin
Robert Kluin

Reputation: 8292

How are you going to query your tags, will you be concerned only with tags from a particular entity group? If that is the case, since you're going to put your Tag entities in a Group entity's entity group, the ReferenceProperty provides no real value. You could instead use tag_entity.key().parent() to get the Group entity's key or tag_entity.parent() to get the Group entity itself. You could then use a ListProperty on Group to store the key_names of the tag entities (which I presume will be the actual 'tag').

Since you are replacing all of a group's tags any time the Group entity is updated, have you considered using a ListProperty to store your tags on directly on Group entity. Or, storing a list of tag key_names directly on Group. Either approach would make fetching all tags for a group quite easy and efficient.

Upvotes: 1

Related Questions