2008-12-04 23 views
5

Estoy tratando de validar que una URL enviada no existe en la base de datos.Problemas al generar un ValidationError en un formulario de Django

Las partes pertinentes de la clase Form aspecto como éste:

from django.contrib.sites.models import Site 
class SignUpForm(forms.Form): 
    # ... Other fields ... 
    url = forms.URLField(label='URL for new site, eg: example.com') 

    def clean_url(self): 
     url = self.cleaned_data['url'] 
     try: 
      a = Site.objects.get(domain=url) 

     except Site.DoesNotExist: 
      return url 

     else: 
      raise forms.ValidationError("That URL is already in the database. Please submit a unique URL.") 

    def clean(self): 
     # Other form cleaning stuff. I don't *think* this is causing the grief 

El problema es que, independientemente de lo que el valor a mi juicio, no puede elevar el ValidationError. Y si hago algo como esto en el método clean_url():

if Site.objects.get(domain=url): 
    raise forms.ValidationError("That URL is already in the database. Please submit a unique URL.") 

cuando me siento un error DoesNotExist, incluso para las direcciones URL que ya existen en la base de datos. ¿Algunas ideas?

Respuesta

4

canal de Django en IRC me salvó aquí. El problema era que el URLField.clean() hace dos cosas que no esperaba:

  1. Si ningún esquema de URL está presente (por ejemplo, http: //) antepone los métodos 'http: //' a la url
  2. el método también agrega una barra inclinada.

Los resultados se devuelven y almacenan en clean_data del formulario. Así que estaba revisando cleaned_data['url'] esperando algo así como example.com y obteniendo realmente http://example.com/. Baste decir, el cambio de mi método clean_url() a las siguientes obras:

def clean_url(self): 
     url = self.cleaned_data['url']   
     bits = urlparse(url) 
     dom = bits[1] 
     try: 
      site=Site.objects.get(domain__iexact=dom) 
     except Site.DoesNotExist: 
      return dom 
     raise forms.ValidationError(u'That domain is already taken. Please choose another') 
1

Lo hago de esta manera. Es un poco mas simple

try: 
    a = Site.objects.get(domain=url) 
    raise forms.ValidationError("That URL is already in the database. Please submit a unique URL.") 
except Site.DoesNotExist: 
    pass 
return url 
+0

no es bueno - El error no quede levantada cuando debe. – saturdayplace

+0

Tienes otros problemas, entonces. Esto tiene que funcionar. ¿Estás ejecutando "manage.py testserver" y obteniendo una nueva base de datos vacía cada vez que corres? ¿Estás ejecutando "manage.py runserver"? –

+0

De acuerdo. Existe una buena posibilidad de que sus otros métodos de validación _are_ "causen el dolor". –

0

Creo que puede devolver '' y rellenar _errores.

msg = u"That URL is already in the database. Please submit a unique URL." 
self._errors["url"]=ErrorList([msg]) 
return '' 

o

from django.contrib.sites.models import Site 
class SignUpForm(forms.Form): 
    # ... Other fields ... 

url = forms.URLField(label='URL for new site, eg: example.com') 

def clean_url(self): 
    url = self.cleaned_data['url'] 
    try: 
     a = Site.objects.get(domain=url) 
     raise forms.ValidationError("That URL is already in the database. Please submit a unique URL.") 
    except Site.DoesNotExist: 
     return url 
    return '' 

def clean(self): 
    # Other form cleaning stuff. I don't *think* this is causing the grief 
+0

-1: levantar ValidationError es la forma correcta. Rellenar self._errors manualmente es un truco sin una buena razón. –

+0

+1: a pesar de todo me fue útil – rplevy

Cuestiones relacionadas