2010-03-08 133 views
1

我試圖驗證含有ModelChoiceField形式:驗證ModelChoiceField在Django形成

forms.py:

from django import forms 

from modelchoicetest.models import SomeObject 

class SomeObjectAddForm(forms.ModelForm): 
    class Meta: 
     model = SomeObject 

models.py:

from django.db import models 

class SomeChoice(models.Model): 
    name = models.CharField(max_length=16) 

    def __unicode__(self): 
     return self.name 

class SomeObject(models.Model): 
    choice = models.ForeignKey(SomeChoice) 

views.py:

from django.shortcuts import render_to_response 
from django.template import RequestContext 
from django.http import HttpResponseRedirect 
from django.core.urlresolvers import reverse 

from forms import SomeObjectAddForm 

def add(request): 
    if request.method == 'POST': 
     form = SomeObjectAddForm(request.POST) 
     if form.is_valid(): 
      form.save() 
      return HttpResponseRedirect(reverse('modelchoicetest_add')) 
    else: 
     form = SomeObjectAddForm() 

    return render_to_response('modelchoicetest/index.html', 
           {'form': form}, 
           context_instance=RequestContext(request)) 

當它用於我在正常情況下,一切都很順利。但是我希望保護表單不受無效輸入的影響。很明顯,我必須得到forms.ValidationError當我把無效的值在這個領域,是不是?但是,如果我嘗試提交表單,在「somechoice」領域的「無效」值,我得到

ValueError: invalid literal for int() with base 10: 'invalid' 

,而不是預期的forms.ValidationError。我該怎麼辦?我試圖把一個def clean_somechoice(self)檢查該字段,但沒有奏效:ValueError異常發生之前談到clean_somechoice()

另外,我不認爲這是一個很好的解決方案,必須有更多的東西簡單,但我只是錯過了。

以下是完整回溯:

Traceback: 
File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py" in get_response 
    101.      response = callback(request, *callback_args, **callback_kwargs) 
File "/home/andrey/public_html/example/modelchoicetest/views.py" in add 
    11.   if form.is_valid(): 
File "/usr/local/lib/python2.6/dist-packages/django/forms/forms.py" in is_valid 
    120.   return self.is_bound and not bool(self.errors) 
File "/usr/local/lib/python2.6/dist-packages/django/forms/forms.py" in _get_errors 
    111.    self.full_clean() 
File "/usr/local/lib/python2.6/dist-packages/django/forms/forms.py" in full_clean 
    276.      value = field.clean(value) 
File "/usr/local/lib/python2.6/dist-packages/django/forms/fields.py" in clean 
    154.   value = self.to_python(value) 
File "/usr/local/lib/python2.6/dist-packages/django/forms/models.py" in to_python 
    911.    value = self.queryset.get(**{key: value}) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py" in get 
    330.   clone = self.filter(*args, **kwargs) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py" in filter 
    536.   return self._filter_or_exclude(False, *args, **kwargs) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py" in _filter_or_exclude 
    554.    clone.query.add_q(Q(*args, **kwargs)) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py" in add_q 
    1109.        can_reuse=used_aliases) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/query.py" in add_filter 
    1048.     connector) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/where.py" in add 
    66.    value = obj.prepare(lookup_type, value) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/where.py" in prepare 
    267.    return self.field.get_prep_lookup(lookup_type, value) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py" in get_prep_lookup 
    314.    return self.get_prep_value(value) 
File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/__init__.py" in get_prep_value 
    496.   return int(value) 

Exception Type: ValueError at/
Exception Value: invalid literal for int() with base 10: 'invalid' 
+0

請發佈*完整*錯誤追溯 - 您沒有提供足夠的信息來調試此。 – 2010-03-08 12:16:22

+0

在你的例子的上下文中,回溯看起來如何? – gruszczy 2010-03-08 13:49:00

+0

你使用的是什麼版本的Django? – gruszczy 2010-03-08 13:53:34

回答

1

它看起來對我來說,異常是由實際ModelChoiceField對象的clean方法提高。由於是外鍵,Django期待int,這將代表SomeChoicepk。你究竟如何將invalid轉換成表格?

迴應置評

如果你真的覺得你需要抓住這個,你可以通過創建一個新的領域覆蓋默認ModelChoiceField稱爲choice並在to_field_name kwarg傳遞到ModelChoiceField__init__方法。這樣Django不會在pk上過濾,也不會引發這種異常。

我個人不會使用這個解決方案。不需要適應黑客入侵您的表單的用戶。

+0

我可以通過修改客戶端的表單(很多工具可以做到這一點,我使用FF Webdeveloper「編輯HTML」功能)來輕鬆地傳遞'invalid'。我知道這不是每個客戶都會做的事情,但我不想讓任何人有機會在我的網站上提出未處理的例外情況,並可能用電子郵件通知等方式炸燬我。 – Andrey 2010-03-08 14:24:33

+0

我剛剛更新了我的答案並提供了回覆給你評論 – Zach 2010-03-08 14:53:29

+1

謝謝!我會嘗試。那不是關於容納,而是正確處理錯誤。我認爲類似的情況是例如django註釋表單或csrf_token中的蜜罐字段。如果黑客將不正確的數據發佈給這些人,首先會給你驗證錯誤,第二會給你403拒絕,但沒有人會引發未處理的異常,對吧? – Andrey 2010-03-08 15:13:41