简体   繁体   English

在Django表单中验证ModelChoiceField

[英]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 ,该值可以代表SomeChoicepk 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM