当前位置:  开发笔记 > 编程语言 > 正文

Django表单:隐藏字段中的外键

如何解决《Django表单:隐藏字段中的外键》经验,为你挑选了3个好方法。

我的表格:

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提取到表单的所有者字段中?如果是这样,在我尝试验证表单之前,如何以及何时将其映射回去?



1> ayaz..:

我怀疑__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:




2> SingleNegati..:

嗯...

这实际上可能是一个安全漏洞.

假设恶意攻击者制作了一个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



3> Guðmundur H..:

将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

推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有