感谢Insin回答之前与此相关的question。
他的回答有效并且运作良好,然而,我对'cleaning_data'的提供感到困惑,或者更确切地说,如何使用它?
class RegistrationFormPreview(FormPreview):
preview_template = 'workshops/workshop_register_preview.html'
form_template = 'workshops/workshop_register_form.html'
def done(self, request, cleaned_data):
# Do something with the cleaned_data, then redirect
# to a "success" page.
registration = Registration(cleaned_data)
registration.user = request.user
registration.save()
# an attempt to work with cleaned_data throws the error: TypeError
# int() argument must be a string or a number, not 'dict'
# obviously the fk are python objects(?) and not fk_id
# but how to proceed here in an easy way?
# the following works fine, however, it seems to be double handling the POST data
# which had already been processed in the django.formtools.preview.post_post
# method, and passed through to this 'done' method, which is designed to
# be overidden.
'''
form = self.form(request.POST) # instansiate the form with POST data
registration = form.save(commit=False) # save before adding the user
registration.user = request.user # add the user
registration.save() # and save.
'''
return HttpResponseRedirect('/register/success')
为了快速参考,这里是post_post方法的内容:
def post_post(self, request):
"Validates the POST data. If valid, calls done(). Else, redisplays form."
f = self.form(request.POST, auto_id=AUTO_ID)
if f.is_valid():
if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
return self.failed_hash(request) # Security hash failed.
return self.done(request, f.cleaned_data)
else:
return render_to_response(self.form_template,
{'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
context_instance=RequestContext(request))
答案 0 :(得分:9)
我以前从未尝试过使用ModelForm进行的操作,但您可以使用**运算符将您的cleaning_data字典扩展为您的注册构造函数所需的关键字参数:
registration = Registration (**cleaned_data)
模型类的构造函数接受Django的Model元类转换为结果对象上的实例级属性的关键字参数。 **运算符是一种调用约定,它告诉Python将字典扩展为那些关键字参数。
换句话说......
你目前所做的就是这个:
registration = Registration ({'key':'value', ...})
这不是你想要的,因为构造函数需要关键字参数而不是包含关键字参数的字典。
你想要做的是这个
registration = Registration (key='value', ...)
这类似于:
registration = Registration (**{'key':'value', ...})
同样,我从来没有尝试过,但只要你没有对你的表单做任何花哨的事情,例如为你的注册构造函数不期望添加新的属性,它似乎会起作用。在这种情况下,您可能必须在执行此操作之前修改cleaning_data字典中的项目。
但是,通过浏览表单预览实用程序,看起来似乎正在失去ModelForms中固有的一些功能。也许您应该将您的用例带到Django邮件列表中,看看是否有一个潜在的增强功能可以使这个API更好地使用ModelForms。
修改强>
除了我上面描述的内容之外,你总是可以“手动”从您的cleaning_data字典中提取字段,并将它们传递给您的注册构造函数,但需要注意的是,您必须记住将此代码更新为您将新字段添加到模型中。
registration = Registration (
x=cleaned_data['x'],
y=cleaned_data['y'],
z=cleaned_data['z'],
...
)