Reputation: 6832
I'm playing around with google app engine a little but got stuck processing a POST request using a ReferenceProperty
. I'm creating a dropdown menu from the existing categories like so:
<select name="mydropdown">
<label for="category">category:</label>
{% for c in cats %}
<option value={{ c.title }} name="category"> {{ c.title }} </option>
{% endfor %}
</select>
The form has more fields to it:
<div>
<label for="title">Title:</label>
{{ e_form.title }}
</div>
....
The option value needs to be part of {{ e_form }}
, in this case {{ e_form.category }
. How can I establish such a cross reference? Or what would be a different good solution for my problem?
Have a look at my models (the class CatForm()
is used elsewhere):
class Category(db.Model):
title = db.StringProperty()
slug = db.StringProperty()
description = db.StringProperty(multiline=True)
class CatForm(djangoforms.ModelForm):
class Meta:
model = Category
exclude = ['slug']
class Entry(db.Model):
category = db.ReferenceProperty(Category)
author = db.UserProperty()
title = db.StringProperty(required=True)
slug = db.StringProperty(required=True)
body = db.TextProperty(required=True)
published = db.DateTimeProperty(auto_now_add=True)
updated = db.DateTimeProperty(auto_now=True)
class EntryForm(djangoforms.ModelForm):
class Meta:
model = Entry
exclude = ['published','updated']
Like this I can't create a form instance with my POST data. Well, I can create it but my selected category won't be in there.
def post(self):
data = EntryForm(data=self.request.POST)
...
Thanks for any advice.
Upvotes: 0
Views: 125
Reputation: 6832
Here the complete answer if someone wants to know. Like @Daniel said, the field name comes from the select not the option. So this is how the select should look like:
<select name="category">
<label for="category">category:</label>
{% for c in cats %}
<option>{{ c.title }} </option>
{% endfor %}
</select>
You can either create an instance of the parent class using the category title
c = self.request.get("category")
cat_get = Category.all().filter("title =", c).get()
or use the key as the option
name in the template like so:
<option name="{{ c.key }}">{{ c.title }} </option>
Then you can use the key directly to get the Category
object.
cat_obj = db.get(db.Key(key_name))
This is all the data I need to make a new entry. The commit=False
keyword argument returns an object that hasn't been saved to the DB yet. That makes it possible to set single attributes manually. In this case the category. See This link for details on the Django save()
-method. To save the data the put()
-method is used.
new_entry = form_data.save(commit=False)
new_entry.category = cat_get
new_entry.put()
Putting all the pieces together the handler could look like this.
class NewEntry(webapp.RequestHandler):
def post(self):
form_data = EntryForm(self.request.POST)
if form_data.is_valid():
c = self.request.get("category")
cat_get = Category.all().filter("title =", c).get()
new_entry = form_data.save(commit=False)
new_entry.category = cat_get
new_entry.put()
self.redirect("/main" )
else:
self.response.set_status(500)
Upvotes: 0