2010-03-08 2 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)) 

Когда он используется i В нормальных условиях все идет хорошо. Но я хотел бы защитить форму от недопустимого ввода. Это довольно очевидно, что я должен получить 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

Пожалуйста, разместите * полный * trace traceback - вы не дали достаточно информации для отладки этого. –

+0

В контексте вашего примера, как выглядит трассировка? – gruszczy

+0

Какую версию django вы используете? – gruszczy

ответ

1

Он смотрит на меня, как исключение поднимается по clean методом фактического ModelChoiceField объекта. Поскольку это внешний ключ, Django ожидает int, который будет представлять собой pk для SomeChoice. Как именно вы проходите invalid в форму?

ОТВЕТ НА ОТЗЫВ

Если вы действительно чувствуете, что вам нужно, чтобы поймать это, вы можете попробовать переопределить значение по умолчанию ModelChoiceField, создавая новое поле под названием choice и передать в to_field_name kwarg в метод ModelChoiceField__init__. Таким образом Django не будет фильтровать на pk и не будет поднимать это исключение.

Лично я бы не использовал это решение. Нет необходимости размещать пользователя, который взламывает вашу форму.

+0

Я могу легко передать 'invalid', изменив форму на стороне клиента (многие инструменты могут это сделать, я использовал функцию FF Webdeveloper« Редактировать HTML »).Я понимаю, что это не то, что каждый клиент будет делать, но я не хочу никому давать возможность поднимать необработанное исключение на моем сайте и потенциально бомбить меня уведомлениями по электронной почте и т. Д. – Andrey

+0

Я только что обновил свой ответ с ответом вам комментариев – Zach

+1

Спасибо! Я попробую это. Ну, дело не в размещении, а в правильном обращении с ошибками. Я думаю, что подобными случаями являются, например, поле honeypot в форме комментариев django или csrf_token. Если хакер отправляет им неправильные данные, сначала вы получите ошибку проверки, а вторая даст вам 403 отказа, но никто не приведет к необработанному исключению, верно? – Andrey

Смежные вопросы