views:

647

answers:

2

How can I get at the Labels data from within my Task model?

class Task(db.Model):
  title = db.StringProperty()

class Label(db.Model):
  name = db.StringProperty()

class Tasklabel(db.Model):
  task = db.ReferenceProperty(Task)
  label = db.ReferenceProperty(Label)

creating the association is no problem, but how can I get at the labels associated with a task like:

task = Task.get('...')
for label in task.labels
A: 

Don't you want a ListProperty on Task like this to do a many-to-many?

class Label(db.Model)
   name = db.StringProperty()

   @property
   def members(self):
      return Task.gql("WHERE labels = :1", self.key())

class Task(db.Model)
   title = db.StringProperty();
   labels = db.ListProperty(db.Key)

Then you could do

foo_label = Label.gql("WHERE name = 'foo'").get()
task1 = Task.gql("WHERE title = 'task 1'").get()
if foo_label.key() not in task1.labels:
  task1.labels.append(foo_label.key())
task1.put()

There's a thorough article about modeling entity relationships on Google code. I stole the code above from this article.

seth
that may be the solution, I thought I could do it without
kristian nissen
Mind if I ask why? The appengine datastore seems to make it easy to do away with the join tables like TaskLabel that are common in RDBMS.
seth
I see that using the listproperty may be the correct solution
kristian nissen
+2  A: 

This worked for me with your current datamodel:

taskObject = db.Query(Task).get()
for item in taskObject.tasklabel_set:
        item.label.name

Or you could remove the Label class and just do a one-to-many relationship between Task and TaskLabel:

class Task(db.Model):
        title = db.StringProperty()

class TaskLabel(db.Model):
        task = db.ReferenceProperty(Task)
        label = db.StringProperty()

Then

taskObject = db.Query(Task).get()
for item in taskObject.tasklabel_set:
        item.label

Here is a tip from the Google article on modeling relationships in the datastore

By defining it as a ReferenceProperty, you have created a property that can only be assigned values of type 'Task'. Every time you define a reference property, it creates an implicit collection property on the referenced class. By default, this collection is called _set. In this case, it would make a property Task.tasklabel_set.

The article can be found here.

I also recommend playing around with this code in the interactive console on the dev appserver.

Jason Rikard
how can I "play around with this code in the interactive console on the dev appserver"? Django has one, but I haven't found one for GAE.
kristian nissen
When you have the dev_appserver running on your local machine you can go to http://localhost:8080/_ah/admin/interactive and test snippets of code there. You'll have to provide the usual import statements for your code to work. Type your code and hit 'run program' at the bottom.
Jason Rikard
Did this answer your question?
Jason Rikard