7
votes

Django Modelform Supprimer "Obligatoire" Attribut basé sur un autre choix sur le terrain

J'ai modeloForm avec plusieurs champs. Certains champs sont nécessaires, certains pas. De plus, j'ai un champ de sélection avec des choix différents, et je veux faire des champs "requis" ou non basé sur ce choix de champ sélectionné.

J'ai essayé en mode propre () de formulaire xxx < / Pré>

mais ça ne marche pas


0 commentaires

3 Réponses :


3
votes

Vous avez la bonne idée, mais le problème est que les validations de champ individuelles sont déjà exécutées avant le formulaire propre. Vous avez plusieurs options. Vous pouvez rendre le champ non requis et gérer la logique du moment où il est requis dans votre form.clean code>. Ou vous pouvez laisser le champ selon les besoins et supprimer les erreurs de validation qu'il pourrait élever dans le nettoyage.

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


0 commentaires

10
votes

Voir la documentation Django sur champs de nettoyage et de validation qui dépendent de l'autre . La pratique standard serait d'effectuer la manipulation suivante à la place:

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


5 commentaires

Merci. Cette idée m'a aidé à l'obtenir!


Je dois faire une validation similaire (Django 1.4) mais le champ que je teste est lu que je ne l'ai pas dans mon nettoyage_data (BTW - je le fais dans l'administrateur). Une idée de savoir comment accéder à la valeur de ce champ en lecture seule? 10x


Trouvé la solution - form.instance contient toutes les données pertinentes et les données modifiées sont incluses dans form.changed_data


Bien que cela ressemble à la bonne approche, je pense que la logique de la vérification quelque_field == quelque_value pourrait être dupliqué dans la vue. Je ne sais pas quelle est la bonne façon? Vivre avec redondance ou déplacer cette validation pour voir?


@buffer: Je ne vois pas pourquoi la vue devrait répéter la logique de validation puisque le formulaire le fait déjà. Si la vue a un chèque similaire (afin de déterminer s'il faut utiliser autre_field ou non), cela ne peut pas être évité dans un système à deux passages (1 passage pour validation, 1 passage pour la consommation) Afaict. Si vous préférez, vous pouvez déplacer cette logique à la vue uniquement, mais vous pouvez ensuite répéter la même logique pour plusieurs vues qui utilisent le même formulaire.



2
votes

Si vous souhaitez imprimer un message d'erreur pour le champ requis de manière courante, vous pouvez le faire:

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']])


1 commentaires

Cette réponse est vraiment, vraiment utile! Merci beaucoup !