Set parent in a ModelForm in Google App Engine
I want to create an Entity Group relationship in an Entity that is being created through a ModelForm.
开发者_如何学编程How do I pass the parent instance and set the parent=
attribute in the ModelForm?
I'll be interested to see if you get any good solutions to this problem. My own solution, which is far from elegant, is to do this:
book = models.Book(title='Foo')
chapter = models.Chapter(parent=book, title='dummy')
form = forms.ChapterForm(request.POST, request.FILES, instance=chapter)
Basically, I first create a dummy object (chapter
in this case) with the correct parent relationship and then pass that as the instance
argument to the form's constructor. The form will overwrite the throwaway data I used to create the dummy object with the data given in the request. At the end, to get the real child object, I do something like this:
if form.is_valid():
chapter = form.save()
# Now chapter.parent() == book
I subclassed djangoforms.ModelForm and added a create method*:
class ModelForm(djangoforms.ModelForm):
"""Django ModelForm class which uses our implementation of BoundField.
"""
def create(self, commit=True, key_name=None, parent=None):
"""Save this form's cleaned data into a new model instance.
Args:
commit: optional bool, default True; if true, the model instance
is also saved to the datastore.
key_name: the key_name of the new model instance, default None
parent: the parent of the new model instance, default None
Returns:
The model instance created by this call.
Raises:
ValueError if the data couldn't be validated.
"""
if not self.is_bound:
raise ValueError('Cannot save an unbound form')
opts = self._meta
instance = self.instance
if self.instance:
raise ValueError('Cannot create a saved form')
if self.errors:
raise ValueError("The %s could not be created because the data didn't "
'validate.' % opts.model.kind())
cleaned_data = self._cleaned_data()
converted_data = {}
for name, prop in opts.model.properties().iteritems():
value = cleaned_data.get(name)
if value is not None:
converted_data[name] = prop.make_value_from_form(value)
try:
instance = opts.model(key_name=key_name, parent=parent, **converted_data)
self.instance = instance
except db.BadValueError, err:
raise ValueError('The %s could not be created (%s)' %
(opts.model.kind(), err))
if commit:
instance.put()
return instance
Usage is simple:
book = models.Book(title='Foo')
form = forms.ChapterForm(request.POST)
chapter = form.create(parent=book)
Note that I did not copy/paste the code that lets you specify the key_name in request.POST, instead I have it passed as an argument to create.
* Code is modified from the save method of the original modelform in google.appengine.ext.db.djangoforms
.
精彩评论