2011-09-06 49 views
0

首先是代碼。 的的ModelForm(IM 1和IM是models.ImageField):帶有ImageFields的ModelForm,如果驗證錯誤未正確清除

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包含一個有效的圖像,我檢查旁邊的清除複選框,但不檢查檢查和提交,fo rm返回一個錯誤,說checkme是必需的。雖然表單返回錯誤,但看起來好像im1已被清除。實際上它並不是因爲如果我重新加載表單im1顯示備份與其文件和清除複選框。

我的問題是我該如何解決這個問題?這是我正在做的事情還是這個與Django有關?

回答

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實例創建綁定表單,並將無效表單和新創建的表單都傳遞給模板,並使用無效表單顯示錯誤,另一個表單顯示其餘表單:

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}) 

OR我會做同樣的事情,但是從非有效形式向新創建的窗體保存錯誤,這樣你就不會得到處都是用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實現。

我不認爲這樣做是值得的。正如我之前所說,你只是爲你的用戶創造更多的工作...

+0

感謝您的幫助,我會嘗試一些出來,它看起來很有前途。我讓用戶做了兩次完全相同的操作,因爲這是一個簡化的測試用例。在真實情況下,圖像是個人資料圖片,並且一個人必須檢查一個框,表示他們承認圖片將在網站上公開。另一種產生相同結果的場景是,如果您沒有檢查框,但是請檢查im1並給im2一個非圖像。表單返回im2錯誤,im1看起來好像已被清除。這就是我想要避免的,如果不是的話,im1或2看起來會被清除。 – joshcartme

+0

我想我明白你現在說的話。您需要記住您可以查看request.POST和request.FILES字典的內容。你可以檢查是否選中了「清除」,如果是,你可以手動刪除圖像,這樣如果他們有表單錯誤並刷新頁面,它確實永遠消失了,而不是再次出現。 –