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开发者_StackOverflow中文版 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 Tag
s. Any time I modify a Group
, I will be updating it completely, replacing all of it's Tag
s 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:
- Update groups - create or update 6 groups. If create, then create the tags for the group. If update, completely replace the tags for the group (removing old ones) - happens every 5 minutes or so
- Read recent groups - get the 6-20 (undecided yet) most recently modified groups, no need to load their tags
- Read single group - get the information for a single group, including it's tags (each one will have between 10 and 20 tags)
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.
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_name
s 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.
modeling in appengine
one-to-many using parent in that will come in handy for you
you can also consider other examples
精彩评论