我的表格:
class PlanForm(forms.ModelForm): owner = forms.ModelChoiceField(label="", queryset=Profile.objects.all(), widget=forms.HiddenInput()) etc... class Meta: model = Plan
模型中的所有者是个人资料的ForeignKey.
当我设置此表单时,我将"owner"的值设置为Profile对象.
但是当这个出现在表单上时,它似乎包含了这样的配置文件的名称:
当提交表单并返回到我的views.py时,我尝试像这样处理它:
form = PlanForm(request.POST) ... if form.is_valid(): plan = form.save() return HttpResponseRedirect('/plans/%s'%plan.id) # Redirect after POST
但是,我得到的是类型转换错误,因为它无法将字符串"phil"(保存到"owner"字段中的用户名称)转换为Int以将其转换为ForeignKey.
那么这里发生了什么.ModelForm是否应将外键表示为数字并透明地处理它?或者我是否需要将自己的ID提取到表单的所有者字段中?如果是这样,在我尝试验证表单之前,如何以及何时将其映射回去?
我怀疑__unicode__
Profile模型实例的repr
方法或其设置为返回除以外的值self.id
.例如,我只是设置它:
# models.py class Profile(models.Model): name = models.CharField('profile name', max_length=10) def __unicode__(self): return u'%d' % self.id class Plan(models.Model): name = models.CharField('plan name', max_length=10) profile = models.ForeignKey(Profile, related_name='profiles') def __unicode__(self): return self.name # forms.py class PlanForm(forms.ModelForm): profile = forms.ModelChoiceField(queryset=Profile.objects.all(), widget=forms.HiddenInput()) class Meta: model = Plan # views.py def add_plan(request): if request.method == 'POST': return HttpResponse(request.POST['profile']) profile = Profile.objects.all()[0] form = PlanForm(initial={'profile':profile}) return render_to_response('add_plan.html', { 'form':form, }, context_instance=RequestContext(request))
有了它,我看到在模板中呈现的PlanForm.profile:
嗯...
这实际上可能是一个安全漏洞.
假设恶意攻击者制作了一个POST(例如,通过使用FireBug中的XmlHttpRequest)并将配置文件术语设置为某个古怪值,例如您的配置文件ID.可能不是你想要的?
如果可能,您可能希望从请求对象本身获取配置文件,而不是从POST值提交的配置文件.
form = PlanForm(request.POST) if form.is_valid(): plan = form.save(commit=False) plan.owner = request.user.get_profile() plan.save() form.save_m2m() # if neccesary
将Profile对象分配给表单时,Django将其字符串化并将输出用作表单中的值.你会期望的是Django使用对象的ID代替.
幸运的是,解决方法很简单:只需给出Profile对象的表单主键值:
form = PlanForm(initial={'profile': profile.pk})
另一方面,当您使用绑定表单时,它们的工作更加明智:
form = PlanForm(request.POST) if form.is_valid(): print form.cleaned_data['profile'] # the appropriate Profile object