views:

64

answers:

2

I am using google-app-engine webapp, part of the code is :

class Post(db.Model):
    title = db.StringProperty(required=True)
    def categories(self):
        return (x.category for x in self.postcategory_set)

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

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


class sss(webapp.RequestHandler):
  def get(self):
    obj1 = Post(title='hhaa')
    #obj1.title = 'haha'
    obj1.put()

    obj2 = Category()

    obj2.name='haha-kao'

    obj2.put()
    obj3=PostCategory()
    obj3.post=obj1
    obj3.category=obj2
    obj3.put()
    self.response.out.write(obj1.categories().get().name)

but I get an error:

Traceback (most recent call last):
  File "D:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 511, in __call__
    handler.get(*groups)
  File "D:\zjm_code\helloworld\a.py", line 131, in get
    self.response.out.write(obj1.categories().get().name)
AttributeError: 'generator' object has no attribute 'get'

so how can I obtain all values of the genexp I wrote?

+1  A: 

It is categories().next() that you need. Generators have no get.

msw
where is the all methods of the Generators ? thanks
zjm1126
see my second answer.
msw
+1  A: 

If you wanted an all method you should return a list comprehension instead of a generator:

return [x.category for x in self.postcategory_set]

but since postcategory_set is already an iterable (because you iterated it)

return self.postcategory_set

would be more natural, but that would give the caller a reference to your private, mutable data, except in this case Post.postcategory_set is not really a set type but rather an instance of google.app.engine.ext.db.Query which is indeed iterable but not mutable.

And you didn't ask, but your model is funny, with the PostCategory table being unnecessary when you could have:

class Post(db.Model):
    title = db.StringProperty(required=True)
    category = db.ReferenceProperty(Category)
    def categories(self):
        return list(self.postcategory_set)

And drop PostCategory completely.

msw
You definitely shouldn't use "list(self.postcategory_set)" - this will iterate over the related entities, doing fetches in batches of 20. Instead, use self.postcategory_set.fetch(some_num), which returns a list.
Nick Johnson
@Nick: agreed, thanks for the clarification. I was trying to work in the context of the OP; that context isn't "best practice" but it also appears that the OP is just learning and working with toy databases.
msw
Absolutely- I recognized the context, just wanted to point out that there's a better domain-specific solution available.
Nick Johnson