views:

93

answers:

1

Hello!

I have modular project structure, like this:

./main.py
./app.yaml
../articles
.../__init__.py
.../models.py
../blog
.../__init__.py
.../models.py
../comments
.../__init__.py
.../models.py

I have defined models in file models.py for each package (this is application). I have defined next models for "comments" application:

class Comment(db.Model):
    author      = db.UserProperty(auto_current_user_add=True)
    title       = db.StringProperty(default="Title")
    text        = db.TextProperty("Message", default="Your message")
    # references to any model
    object      = db.ReferenceProperty()

and in "articles" application I have defined next models:

class Article(db.Model):
    author      = db.UserProperty(auto_current_user_add=True)
    title       = db.StringProperty(default="Title")
    text        = db.TextProperty("Message", default="Your message")

1) On first loading of page - I create new article:

from articles.models import Article
article = Article(title="First article", text="This is first article")
article.put()

2) On second loading of page I create new comment:

from articles.models import Article
from comments.models import Comment
article = Article.get_by_id(1)
comment = Comment(title="First comment", text="This is first comment")
comment.put()

3) On thind loading of page, I want to see all comments for all articles, blogs, and other objects in whole datastore:

from comments.models import Comment
comments = Commen.all()
for comment in comments:
    # print comment and article title
    print "%s: %s" % (comment.title, comment.object.title)

Actual result: "KindError: No implementation for kind 'Article'"

Expected result: automatically detect object type for reference and load this class

See more on: http://code.google.com/p/appengine-framework/issues/detail?id=17
Project need your help!

+1  A: 

In order to be able to return entities of a given kind, App Engine has to be able to find the Model class for it. There's no mechanism built in for doing so, because all it has to look it up with is the entity kind, which can be any arbitrary string.

Instead, import the modules containing the models you may reference from the module containing the Comment model. That way, any time you can perform a query on Comment, all the relevant models are already loaded.

Nick Johnson
Now I build administration section for whole website. And, I need show all comments in one place. I dont know, what type of model contained in this ReferenceProperty.Maybe exists way to get information about ReferenceProperty before create object of this model? This is help me load model class before create instance of this class.
Anton Danilchenko
No, there's no way to do this. The only information the ReferenceProperty has is the key of the entity being referenced, which contains the Kind name, which is not enough information on its own to find the model definition. Simply make sure that you import all the modules that contain models you may need before you execute queries.
Nick Johnson
I think that loading all models from all applications - not a good idea. I need to find easy solution.I know, that Django uses "contenttypes" application, where defined relationship between application and model. I think, that in this case was created table in database with next columns: id, application name, model name. This information enought for load and create model instance.But, how to work with reference properties in this case by calling collection by name. For example:article = Article.get_by_id(1)for comment in article.comments: print comment.titleThanks!
Anton Danilchenko
As I said in my previous answer, "No, there's no way to do this". There is simply not enough information in a kind to find the Model class that defines it. The only way around this would be to either build your own datastore interface, or heavily monkeypatch the existing one. Alternately, you can do what the App Engine admin console does, and drop down to the low-level google.appengine.api.datastore interface, which represents entities as dicts.
Nick Johnson
OK, you are right, Nick!I will start exploring admin console to do similar things.Now I have next design of application: for each model I add prefix with application name. For example: BlogPost instead of Post, BlogCetegory, BlogTag, BlogComment, etc. In this case, I have simple solution for find model in my project - use prefix as application name, where placed all models for this application and import model from this place.
Anton Danilchenko