[英]Validating ModelChoiceField in Django forms
I'm trying to validate a form containing a ModelChoiceField: 我正在尝试验证包含ModelChoiceField的表单:
forms.py: forms.py:
from django import forms
from modelchoicetest.models import SomeObject
class SomeObjectAddForm(forms.ModelForm):
class Meta:
model = SomeObject
models.py: 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: 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))
When it is used in normal circumstances, everything goes just fine. 在正常情况下使用时,一切都很好。 But I'd like to protect the form from the invalid input. 但我想保护表单不受无效输入的影响。 It's pretty obvious that I must get forms.ValidationError when I put invalid value in this field, isn't it? 很明显,当我在此字段中输入无效值时,我必须获取Forms.ValidationError,不是吗? But if I try to submit a form with a value 'invalid' in 'somechoice' field, I get 但是,如果我尝试在“ somechoice”字段中提交一个值为“ invalid”的表单,则会得到
ValueError: invalid literal for int() with base 10: 'invalid'
and not the expected forms.ValidationError. 而不是预期的form.ValidationError。 What should I do? 我该怎么办? I tried to place a def clean_somechoice(self)
to check this field but that didn't work: ValueError happens before it comes to clean_somechoice()
我试图放置一个def clean_somechoice(self)
来检查此字段,但这没有用:ValueError发生在 clean_somechoice()
Plus I don't think this is a good solution, there must be something more simple but I just missed that. 另外,我认为这不是一个好的解决方案,必须有一些更简单的方法,但我只是错过了。
here's the full traceback: 这是完整的追溯:
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'
It looks to me like the exception is being raised by the clean
method of the actual ModelChoiceField
object. 在我看来,实际ModelChoiceField
对象的clean
方法正在引发异常。 Because it's a foreign key, Django is expecting an int
, which would be representative of the pk
for SomeChoice
. 因为它是外键,所以Django期望一个int
,该值可以代表SomeChoice
的pk
SomeChoice
。 How exactly are you passing invalid
into the form? 您如何准确地将invalid
传递给表单?
RESPONSE TO COMMENT 对评论的回应
If you really feel you need to catch this, you can try overriding the default ModelChoiceField
by creating a new field called choice
and pass in the to_field_name
kwarg into the ModelChoiceField
__init__
method. 如果您确实需要抓住这一点,可以尝试通过创建一个名为choice
的新字段来覆盖默认的ModelChoiceField
,并将to_field_name
kwarg传递到ModelChoiceField
__init__
方法中。 This way Django won't be filtering on pk, and won't raise that exception. 这样,Django将不会在pk上进行过滤,也不会引发该异常。
Personally I wouldn't use this solution. 我个人不会使用此解决方案。 There is no need to accommodate user who are hacking your form. 无需容纳正在入侵您的表单的用户。
This is known Django bug: 这是已知的Django错误:
http://code.djangoproject.com/ticket/11716 http://code.djangoproject.com/ticket/11716
And while this bug is not fixed, you can only handle ValueError manually. 而且,尽管此错误没有得到修复,但是您只能手动处理ValueError。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.