2010-03-08 5 views
1

Je suis en train de valider un formulaire contenant un ModelChoiceField:ModelChoiceField en forme Validating 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)) 

Quand il est utilisé Dans des circonstances normales, tout va bien. Mais je voudrais protéger le formulaire de l'entrée invalide. Il est assez évident que je dois obtenir forms.ValidationError quand je mets une valeur invalide dans ce champ, n'est-ce pas? Mais si je tente de présenter un formulaire avec une valeur champ « invalide » dans « de somechoice », je reçois

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

et non le forms.ValidationError attendu. Que devrais-je faire? J'ai essayé de placer un def clean_somechoice(self) pour vérifier ce domaine, mais cela n'a pas fonctionné: ValueError se avant il s'agit de clean_somechoice()

De plus, je ne pense pas que ce soit une bonne solution, il doit y avoir quelque chose de plus simple, mais je juste raté ça.

est complet ici retraçage:

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

Veuillez signaler la trace d'erreur * full * - vous n'avez pas donné suffisamment d'informations pour le déboguer. –

+0

Dans le contexte de votre exemple, à quoi ressemble le retraçage? – gruszczy

+0

Quelle version de django utilisez-vous? – gruszczy

Répondre

1

Il me semble que l'exception est soulevée par la méthode clean de l'objet ModelChoiceField réelle. Parce que c'est une clé étrangère, Django attend un int, ce qui serait représentatif du pk pour SomeChoice. Comment transmettez-vous exactement invalid dans le formulaire?

RÉPONSE AUX COMMENTAIRES

Si vous vous sentez vraiment que vous devez prendre, vous pouvez redéfinissant la valeur par défaut ModelChoiceField en créant un nouveau champ appelé choice et passer dans le to_field_name kwarg dans la méthode ModelChoiceField__init__. De cette façon Django ne filtrera pas sur pk, et ne lèvera pas cette exception.

Personnellement, je n'utiliserais pas cette solution. Il n'est pas nécessaire d'accommoder les utilisateurs qui piratent votre formulaire.

+0

Je peux facilement passer 'invalide' en modifiant le formulaire côté client (beaucoup d'outils peuvent le faire, j'ai utilisé la fonction" Editer HTML "de FF Webdeveloper).Je comprends que ce n'est pas quelque chose que chaque client va faire, mais je ne veux donner à personne la possibilité de soulever une exception non gérée sur mon site, et potentiellement me bombarder avec des notifications par e-mail. – Andrey

+0

Je viens de mettre à jour ma réponse à vous de commenter – Zach

+1

Merci! Je vais essayer ça. Eh bien, il ne s'agit pas d'accommoder, c'est plutôt gérer les erreurs correctement. Je pense que des cas similaires sont par exemple le champ honeypot dans le formulaire de commentaires django ou csrf_token. Si un pirate publie des données incorrectes, vous recevrez une erreur de validation et une seconde 403 Denied, mais aucune ne déclenchera une exception non gérée, n'est-ce pas? – Andrey

Questions connexes