2011-08-17 11 views
7

Tengo ModelForm con varios campos. Algunos de los campos son obligatorios, otros no. También tengo el campo Seleccionar con diferentes opciones, y quiero hacer algunos de los campos "obligatorios" o no basados ​​en esta opción Seleccionar campo.Modelo de Django eliminar el atributo "requerido" basado en otra opción de campo

Probé en el método clean() de la Forma

def clean(self): 
    cleaned_data = self.cleaned_data 
    some_field = cleaned_data.get("some_field") 
    if some_field == 'some_value': 
      self.fields['other_field'].required = False 
    return cleaned_data 

pero no funciona

Respuesta

10

Consulte la documentación de Django en Cleaning and validating fields that depend on each other. La práctica habitual sería llevar a cabo la siguiente manipulación en su lugar:

def clean(self): 
    cleaned_data = self.cleaned_data 
    some_field = cleaned_data.get("some_field") 
    if some_field == 'some_value': 
      # 'other_field' is conditionally required. 
      if not cleaned_data['other_field']: 
       raise forms.ValidationError("'Other_field' is required.") 
    return cleaned_data 
+0

Gracias. ¡Esta idea me ayudó a conseguirlo! – Igor

+0

Necesito hacer una validación similar (Django 1.4) pero el campo que estoy probando es de solo lectura, así que no lo tengo en mis datos limpios (por cierto, lo estoy haciendo en el administrador). ¿Alguna idea de cómo acceder al valor de este campo de solo lectura? 10x – Lin

+0

Encontré la solución - form.instance contiene todos los datos relevantes, y los datos modificados se incluyen en form.changed_data – Lin

1

Usted tiene la idea correcta, pero el problema es que las validaciones de campo individuales ya ha ejecutado antes de que el formulario limpiar. Usted tiene un par de opciones. Puede hacer que el campo no sea necesario y manejar la lógica de cuándo se requiere en su form.clean. O puede abandonar el campo según sea necesario y eliminar los errores de validación que pueda generar en la limpieza.

def clean(self): 
    cleaned_data = self.cleaned_data 
    some_field = cleaned_data.get("some_field") 
    if some_field == 'some_value': 
      if 'other_field' in self.errors: 
       del self.errors['other_field'] 
       cleaned_data['other_field'] = None 
    return cleaned_data 

Esto tiene algunos problemas en que elimina todos los errores, no sólo falta/de errores requeridas. También hay un problema con el cleaned_data. Ahora tiene un campo obligatorio que no está en los datos limpios y es por eso que lo he agregado como None. El resto de su aplicación tendrá que manejar este caso. Puede parecer extraño tener un campo obligatorio que no tenga un valor.

2

Si te gusta imprimir mensaje de error para el campo requerido en forma común, usted puede hacer esto:

def clean(self): 
    cleaned_data = super(PasswordChangeForm, self).clean() 
    token = cleaned_data.get('token') 
    old_password = cleaned_data.get('old_password') 
    if not token and not old_password: 
     self._errors['old_password'] = self.error_class([self.fields['old_password'].error_messages['required']]) 
+0

¡Esta respuesta es realmente útil! Muchas gracias ! – Serafeim

Cuestiones relacionadas