Some help with db models

2 views
Skip to first unread message

Peter Svensson

unread,
Apr 18, 2008, 9:34:57 AM4/18/08
to google-a...@googlegroups.com
Hi, I remember that I've seen a discussion concerning this recently, but I just can't google it. Sorry if this repeats an earlier question.

I want to do something like this;

 
class Project(db.Model):
 ...
  tasks = db.ReferenceProperty(Task)
...
 
class Task(db.Model):
  projects = db.ReferenceProperty(Project)


But I get (of course) "<type 'exceptions.NameError'>: name 'Task' is not defined".  Either way I cut this, it won't work. So, is this impossible, or can one 'predefine' stuff in Python?
Also, if no, can I extract keys and store as IntegerProperties in the other class?

Cheers,
PS

Staz

unread,
Apr 18, 2008, 10:39:57 AM4/18/08
to Google App Engine
You shouldn't need to explicitly reference the tasks from the project
model. You can use "back references" (http://code.google.com/
appengine/docs/datastore/entitiesandmodels.html) to see the tasks
associated with the project.

On Apr 18, 2:34 pm, "Peter Svensson" <psvens...@gmail.com> wrote:
> Hi, I remember that I've seen a discussion concerning this recently, but I
> just can't google it. Sorry if this repeats an earlier question.
>
> I want to do something like this;
>
> class Project(db.Model):
>  ...
>   tasks = db.ReferenceProperty(Task)
> ...
>
> class Task(db.Model):
>   projects = db.ReferenceProperty(Project)
>
> But I get (of course) "*<type 'exceptions.NameError'>*: name 'Task' is not

pick...@gmail.com

unread,
Apr 18, 2008, 12:12:21 PM4/18/08
to Google App Engine
take a look at http://groups.google.com/group/google-appengine/browse_thread/thread/a127d3d62f68d61a

On Apr 18, 9:34 pm, "Peter Svensson" <psvens...@gmail.com> wrote:
> Hi, I remember that I've seen a discussion concerning this recently, but I
> just can't google it. Sorry if this repeats an earlier question.
>
> I want to do something like this;
>
> class Project(db.Model):
> ...
> tasks = db.ReferenceProperty(Task)
> ...
>
> class Task(db.Model):
> projects = db.ReferenceProperty(Project)
>
> But I get (of course) "*<type 'exceptions.NameError'>*: name 'Task' is not

Jeremey Barrett

unread,
Apr 18, 2008, 4:07:54 PM4/18/08
to google-a...@googlegroups.com
BTW, for many-to-many relationships, a join model works nicely. For
example (somewhat contrived of course):

class Post(db.Model):
title = db.StringProperty()
body = db.TextProperty()

def categories(self):
map(lambda x: x.category, self.categorization_set)

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

def posts(self):
map(lambda x: x.post, self.categorization_set)

class Categorization(db.Model):
post = db.ReferenceProperty(Post)
category = db.ReferenceProperty(Category)


Then you can do stuff like this:

p = Post.get_by_id(1)
for c in p.categories():
print c.name

Obviously there is controller glue missing here... I also don't know
if there's a better/recommended way to handle this with appengine.

Regards,
Jeremey.

Peter Svensson

unread,
Apr 18, 2008, 4:18:38 PM4/18/08
to google-a...@googlegroups.com
Thanks anyway Jeremey. This is some good stuff. Since I don't know Python at all, this is secret sauce on a martian level.
Thx*1.0E6

Cheers,
PS

Jeremey Barrett

unread,
Apr 18, 2008, 4:42:54 PM4/18/08
to google-a...@googlegroups.com
On Fri, Apr 18, 2008 at 3:07 PM, Jeremey Barrett
<jeremey...@gmail.com> wrote:
> class Post(db.Model):
> title = db.StringProperty()
> body = db.TextProperty()
>
> def categories(self):
> map(lambda x: x.category, self.categorization_set)

Oops... need a return in there:

def categories(self):
return map(lambda x: x.category, self.categorization_set)

etc.

Jeremey.

Duncan

unread,
Apr 19, 2008, 6:34:33 AM4/19/08
to Google App Engine
On Apr 18, 9:42 pm, "Jeremey Barrett" <jeremey.barr...@gmail.com>
wrote:
> Oops... need a return in there:
>
> def categories(self):
> return map(lambda x: x.category, self.categorization_set)
>
> etc.
>
Or even just:

@property
def categories(self):
return (x.category for x in self.categorization_set)

and use it:

for c in p.categories:
print c.name

A method with no arguments other than self and no side effects is an
obvious candidate to be a property. Also map has its uses, but in this
case it is usual just to use a list or generator comprehension.

Peter Svensson

unread,
Apr 19, 2008, 10:05:51 AM4/19/08
to google-a...@googlegroups.com
I have the following problem now with this code;

class Project(db.Model):
  name = db.StringProperty()
  id = db.IntegerProperty() 
  created_at = db.DateProperty()
  created_by = db.ReferenceProperty(User)
  description = db.TextProperty()
 
  @property
  def tasks(self):
    return (x.category for x in self.task_set) 

error;

..
ttr = <google.appengine.ext.db.ReferenceProperty object at 0x1d1e910>, attr.__property_config__ = <bound method ReferenceProperty.__property_confi...ne.ext.db.ReferenceProperty object at 0x1d1e910>>, cls = <class 'models.Task'>, attr_name = 'responsible'
 /home/peter/projects/gae/google_appengine/google/appengine/ext/db/__init__.py in __property_config__(self=<google.appengine.ext.db.ReferenceProperty object at 0x1d1e910>, model_class=<class 'models.Task'>, property_name='responsible')
 2194       raise DuplicatePropertyError('Class %s already has property %s'
 2195                                    % (self.reference_class.__name__,
 2196                                       self.collection_name))
 2197     setattr(self.reference_class,
 2198             self.collection_name,
self = <google.appengine.ext.db.ReferenceProperty object at 0x1d1e910>, self.collection_name = 'task_set'

<class 'google.appengine.ext.db.DuplicatePropertyError'>: Class User already has property task_set
      args = ('Class User already has property task_set',)
      message = 'Class User already has property task_set'





Can anyone help?



Thx!



PS

Jeremey Barrett

unread,
Apr 19, 2008, 10:13:29 AM4/19/08
to google-a...@googlegroups.com
On Sat, Apr 19, 2008 at 5:34 AM, Duncan <kup...@googlemail.com> wrote:
>
> Or even just:
>
> @property
> def categories(self):
> return (x.category for x in self.categorization_set)
>
> and use it:
>
>
> for c in p.categories:
> print c.name
>
> A method with no arguments other than self and no side effects is an
> obvious candidate to be a property. Also map has its uses, but in this
> case it is usual just to use a list or generator comprehension.

Thanks... the list comprehension is much better, I dunno why I tend
to forget that Python does that.. :)

Jeremey.

Jeremey Barrett

unread,
Apr 19, 2008, 11:08:13 AM4/19/08
to google-a...@googlegroups.com
Can you send the User and Task code? If it's complaining about task_set
on User, then that's where I'd look.

Jeremey.

Peter Svensson

unread,
Apr 19, 2008, 11:11:24 AM4/19/08
to google-a...@googlegroups.com
But.. that's what I don't get. User have no such thing (and isn't supposed to either, AFAIK)
Hre it is;


class User(db.Model):
  googleuser = db.UserProperty()
  type = db.StringProperty()
  allegiance = db.StringProperty()
  name = db.StringProperty()

Strange eh?

Cheers,
PS

Peter Svensson

unread,
Apr 19, 2008, 11:12:41 AM4/19/08
to google-a...@googlegroups.com
..sorry, the kids had me up at six this morning. Here comes Task;




class Task(db.Model):
  projects = db.ReferenceProperty(Project)
  name = db.StringProperty

  id = db.IntegerProperty() 
  created_at = db.DateProperty()
  created_by = db.ReferenceProperty(User)
  description = db.TextProperty()
  created_by = db.ReferenceProperty(User)
  assigned_to = db.ReferenceProperty(User)
  assigned_at = db.DateProperty()
  responsible = db.ReferenceProperty(User)
  responsible_by = db.ReferenceProperty(User)
  responsible_status = db.StringProperty()
  responsible_status_date = db.StringProperty()

Cheers,
PS

Jeremey Barrett

unread,
Apr 19, 2008, 11:17:07 AM4/19/08
to google-a...@googlegroups.com
Ah, there's your problem... you've got a bunch of ReferenceProperty()s
pointing back to User... it's going to build a task_set collection on the user
for each of those... only of course that makes no sense. If you care about
the collections, give them a unique name, by passing collection_name (I
think), like this:

created_by = db.ReferenceProperty(User, collection_name='created_tasks')

Or somesuch.

Or maybe there's a way to suppress the backreferencing altogether, I don't
know off the top of my head.

Jeremey.

Peter Svensson

unread,
Apr 19, 2008, 11:24:37 AM4/19/08
to google-a...@googlegroups.com
Yes!  That worked!!!!! I saw that one *could* rename proeprties, but what it would mean and when it could be used was not obvious.
Thanks!!  IUO a Beer, mate.

Cheers,
PS
Reply all
Reply to author
Forward
0 new messages