具有ImageFields的ModelForm,如果验证错误,则无法正确清除

时间:2011-09-06 18:36:32

标签: django modelform

首先是代码。 ModelForm(im1和im2是models.ImageField):

class TestForm(forms.ModelForm):
    checkme = forms.BooleanField(required=True)

    class Meta:
        model = UserProfile
        fields = ('im1', 'im2')

观点:

def test(request):
    profile = request.user.get_profile()
    form = TestForm(instance=profile)
    if request.method == "POST":
        form = TestForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            form.save()
    return render(request, 'test.html', {'form':form})

模板:

<html>
<head>
<title>Test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" />
</form>
</body>
</html>

问题:

如果im1包含有效图像,并且我选中它旁边的清除复选框但不检查checkme并提交,则表单会返回错误,指出需要checkme。虽然表单返回错误,但似乎已清除im1。实际上它没有,因为如果我重新加载表单im1显示备份其文件和清除复选框。

我的问题是如何解决这个问题?这是我正在做的事情还是与django有关?

1 个答案:

答案 0 :(得分:0)

Django正在按照预期行事。

如果请求是POST请求,那么您的表单将绑定到request.POSTrequest.FILES的数据。如果所有验证都通过,instance=profile只是告诉表单要保存的特定对象。即使您的表单无效,它仍然与已清除图像的数据绑定,这就是您传递给render()的内容。

首先,如果请求方法是POST,则不应创建第一个绑定表单:

def test(request):
    profile = request.user.get_profile()
    if request.method == "POST":
        form = TestForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            form.save()
    else:
        form = TestForm(instance=profile)
    return render(request, 'test.html', {'form':form})

其次,如果他们确实想要删除图像而只是错过了另一个复选框,为什么你希望你的用户做两次同样的操作呢?

如果你真的需要Django这样做,我会做两件事之一。从UserProfile实例创建绑定表单,并将无效表单和新创建的表单都传递给模板,并使用无效表单显示错误,另一个用于显示表单的其余部分: / p>

def test(request):
    profile = request.user.get_profile()
    if request.method == "POST":
        errors_form = TestForm(request.POST, request.FILES, instance=profile)
        if errors_form.is_valid():
            errors_form.save()
            form = errors_form
        else:
            form = TestForm(instance=profile)
            return render(request, 'test.html', {'form':form, 'errors_form': errors_form})
    else:
        form = TestForm(instance=profile)
    return render(request, 'test.html', {'form':form})

或者我会做同样的事情但是将错误从无效的表单保存到新创建的表单中,这样你就不会在整个地方找到renders()

def test(request):
    profile = request.user.get_profile()
    if request.method == "POST":
        errors_form = TestForm(request.POST, request.FILES, instance=profile)
        if errors_form.is_valid():
            errors_form.save()
            form = errors_form
        else:
            form = TestForm(instance=profile)
            #this is left up to you to implement, but you'd do something like
            #form.errors = errors_form.errors
            #and also iterate through every form attribute.errors and assign it to
            #errors_form attribute.errors etc...
    else:
        form = TestForm(instance=profile)
    return render(request, 'test.html', {'form':form})

两者都不是非常优雅的解决方案而且我并不乐观,因为我不完全熟悉Django Forms实现,所以第二个甚至可以按预期工作而不会有更多的黑客攻击。

我不认为这样做是值得的。正如我之前所说,你只是为你的用户创造了更多的工作......