2010-07-12 9 views
12

¿Estoy haciendo algo mal, o es esto en serio lo que los desarrolladores esperan que escriba cada vez que quiero comprobar si dos campos son iguales?¿Por qué es tan complicado verificar si dos contraseñas coinciden en Django?

def clean(self): 
    data = self.cleaned_data 
    if "password1" in data and "password2" in data: 
     if data["password1"] != data["password2"]: 
      self._errors["password2"] = self.error_class(['Passwords do not match.']) 
      del data['password2']  
    return data 

¿Y por qué tengo que validar que el nombre de usuario es único?

def clean_username(self): 
    data = self.cleaned_data['username'] 
    if User.objects.filter(username=data).exists(): 
     raise ValidationError('Username already taken.') 
    return data 

Es un ModelForm. ¿Ya debería saber que hay una restricción única?

Respuesta

26

Esto es lo que yo haría:

Este es el único método limpio debe definir para asegurarse de que 2 contraseñas son correctas y que el nombre de usuario es válido.

Utilice el método clean_fieldname para que no tenga que hacer más trabajo para validar el nombre de usuario.

def clean_password2(self): 
    password1 = self.cleaned_data.get('password1') 
    password2 = self.cleaned_data.get('password2') 

    if not password2: 
     raise forms.ValidationError("You must confirm your password") 
    if password1 != password2: 
     raise forms.ValidationError("Your passwords do not match") 
    return password2 

tienes toda la razón, que no te necesidad de validar el nombre de usuario de ser único, ya que el ModelForm sabe que tiene que ser único.

El problema con su código es que está anulando el método clean(), lo que significa que ModelForm no está haciendo su limpieza "real"().

Para obtener la validación por defecto, llame al super(MyForm, self).clean() o mejor aún no anule clean en absoluto y solo especifique clean_password2.

+0

Creo que esta es la conclusión a la que finalmente llegué también, gracias. Se olvidó de esta pregunta :) – mpen

+0

ooops, no me di cuenta de esto era tan viejo: D –

+0

Todavía está bien que hayas respondido :) – GreenAsJade

1

Es posible que desee agregar una pieza else: para la primera if. Actualmente la función devuelve el data sin establecer ningún error, incluso si una de las contraseñas está ausente: ¿es ese el comportamiento previsto?

else: 
    self._errors["password"] = self.error_class(['One or both of the passwords not found']) 

if "password1" in data and "password2" in data: Esto asegura que ambas contraseñas están presentes. Sin esta línea, obtendrá un error en la siguiente línea donde lee data[password1] y data[password2] si alguno de ellos no está presente.

Las tres líneas siguientes comparan las contraseñas y establece el mensaje de error apropiado, eso es obligatorio, ¿no?

Como dicen, haz las cosas lo más simples posible, ya no.

+0

No creo * que sea necesario ... si alguna de las contraseñas está ausente, eso significa que ya ha habido un error, ¿no es así? Realmente no necesito lanzar un segundo. Y sí, esto podría ser ridículamente más simple. ¿Qué tal cuando defino los campos, escribo 'password2 = PasswordField (validate = EqualTo ('password1'))'? Debería ser capaz de descubrir el resto. – mpen

4

En primer lugar, ¿es en serio quejándose de cuatro líneas de código de placa de caldera? Si realmente te molesta, crea una clase PasswordForm que contenga esa lógica limpia y la sublime para tus propios formularios según sea necesario.

En segundo lugar, usted no tiene que validar las restricciones únicas de forma manual. Como dices, ModelForm lo hace por ti.

Edición después comentario

Esta 'extraña sintaxis' se debe a la comprobación de que dos campos de contraseña partido es un flujo diferente que el esquema normal de las cosas. Para empezar, está comprobando el método principal clean en lugar del campo clean_myfield específico. Si hubiera sido este último, solo se genera una excepción y Django sí elimina los datos del campo.

Así que no, esto no es 7 líneas en cada formulario - vea mi nota acerca de la creación de subclases - y ciertamente no es 7 líneas por múltiples campos, porque no quiere hacer esto para ningún otro tipo de campo

+0

Bueno, algo está dando vueltas en algún lado ... porque acabo de recibir un error duplicado. Solo quería incordiarme un poco porque me estoy cansando de este proyecto :( – mpen

+0

Y son 7 líneas ... de sintaxis extraña. ¿Por qué tengo que verificar si los datos están en el diccionario y luego eliminarlos? ¿Es un diseño un poco extraño? Ya hay una lista de errores, puede verificar que si quiere saber si ha habido un error. Y debería poder adjuntar otro, sin preocuparme realmente, ya tiene un error . Y entonces, ¿por qué devolver datos? Ya estoy manipulando self.cleaned_data, en realidad no parece necesario devolver nada. Si me pasaron en el dict, tal vez. – mpen

+0

Y ni siquiera son solo 7 líneas ... .es 7 líneas en cada formulario volátil, multiplicado por varios campos. – mpen

4

http://k0001.wordpress.com/2007/11/15/dual-password-field-with-django/


Editar: encontramos que el camino de los formulario de administración se ocupa del problema: http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/forms.py

class AdminPasswordChangeForm(forms.Form): 
    """ 
    A form used to change the password of a user in the admin interface. 
    """ 
    password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput) 
    password2 = forms.CharField(label=_("Password (again)"), widget=forms.PasswordInput) 

    def __init__(self, user, *args, **kwargs): 
     self.user = user 
     super(AdminPasswordChangeForm, self).__init__(*args, **kwargs) 

    def clean_password2(self): 
     password1 = self.cleaned_data.get('password1') 
     password2 = self.cleaned_data.get('password2') 
     if password1 and password2: 
      if password1 != password2: 
       raise forms.ValidationError(_("The two password fields didn't match.")) 
     return password2 

    def save(self, commit=True): 
     """ 
     Saves the new password. 
     """ 
     self.user.set_password(self.cleaned_data["password1"]) 
     if commit: 
      self.user.save() 
     return self.user