I’m trying to get my models related using ReferenceProperty, but not have a huge amount of luck. I have 3 levels: Group, Topic, then Pros, and Cons. As in a Group houses many topics, and within each topic could be many Pros and Cons.
I am able to store new Groups nice and fine, but I don’t have any idea how to store topics underneath these groups. I want to link from a page with a link “New topic” underneath each group, that takes them to a simple form (1 field for now). Obviously the URL will need to have some sort of reference to the id of the group or something.
Here are my models:
class Groups(db.Model):
group_user = db.UserProperty()
group_name = db.StringProperty(multiline=True)
group_date = db.DateTimeProperty(auto_now_add=True)
class Topics(db.Model):
topic_user = db.UserProperty()
topic_name = db.StringProperty(multiline=True)
topic_date = db.DateTimeProperty(auto_now_add=True)
topic_group = db.ReferenceProperty(Groups, collection_name='topics')
class Pro(db.Model):
pro_user = db.UserProperty()
pro_content = db.StringProperty(multiline=True)
pro_date = db.IntegerProperty(default=0)
pro_topic = db.ReferenceProperty(Topics, collection_name='pros')
class Con(db.Model):
con_user = db.UserProperty()
con_content = db.StringProperty(multiline=True)
con_date = db.IntegerProperty(default=0)
con_topic = db.ReferenceProperty(Topics, collection_name='cons')
And one function for the actual page I want to show the list of Groups, and then underneath their topics:
class Summary(webapp.RequestHandler):
def get(self):
groups_query = Groups.all()
groups = groups_query.fetch(1000)
template_values = {
'groups': groups,
}
path = os.path.join(os.path.dirname(__file__), 'summary.html')
self.response.out.write(template.render(path, template_values))
And finally the html:
<html>
<body>
<a href="/newgroup">New Group</a>
<br>
{% for group in groups %}
<font size="24">{{ group.group_name|escape }}</font><br> by <b>{{ group.group_user }}</b> at <b>{{ group.group_date }}</b> {{ group.raw_id }}
<br>
<a href="/newtopic?id={{group.key.id}}" >New topice </a>
<br>
<blockquote>
{{ topics.topics_name }}
</blockquote>
{% endfor %}
</body>
</html>
Something that has side effects, such as altering the store (by creating a new object for example) should NOT be an HTTP
GET— GET should essentially only do “read” operations. This isn’t pedantry, it’s a key bit of HTTP semantics — browsers, caches, proxies, etc, are allowed to act on GET as read-only operations (for example by caching results and not passing a request to the server if they can satisfy it from cache).For modifications, use HTTP verbs such as POST (most popular essentially because all browsers implement it correctly) or for specialized operations PUT (to create new objects) or DELETE (to remove objects). I assume you’ll be going to use POST to support a variety of browsers.
To get a POST from a browser, you need either Javascript wizardy or a plain old form with method=post — I’ll assume the latter for simplicity.
If you’re using Django 1.0 (which app engine supports now), it has its own mechanisms to make, validate and accept forms based on models. Other frameworks have their own similarly advanced layers.
If you want to avoid “rich” frameworks you’ll have to implement by hand templates for your HTML forms, direct them (via some kind of URL dispatching, e.g. in app.yaml) to a handler of yours implementing with a
def post(self):, get the data from the request, validate it, form the new object, put it, display some acknowledgment page.What part or parts of the procedure are unclear to you? Your question’s title focuses specifically on reference properties but I’m not sure what problem they are giving you in particular — from the text of your question you appear to be on the right tack about them.
Edit: the OP has now clarified in a comment that his problem is how to make something like:
work. There’s more than one way to do that. If the newtopic URL is served by a static form, the handler for the post “action” of that form could get back to that
id=via theReferer:header (a notorious but unfixable mis-spelling), but that’s a bit clunky and fragile. Better is to have the newtopic URI served by a handler whosedef getgets theid=from the request and inserts it in the resulting form template — for example, in a hidden input field. Have that form’s template contain (among the other fields):put
theidin the context with which you render that template, and it will be in the request that thedef postof the action receiving the form finally gets.