Attention : Le code ci-dessous a été écrit pour une version plus ancienne de Django (avant le Personnalisé Modèles d'utilisateurs ont été introduits). Il contient une condition de course, et ne doit être utilisé qu'avec un niveau d'isolation de transaction de SERIALIZABLE
et les transactions à l'échelle des demandes.
Votre code ne fonctionnera pas, car les attributs des instances de champ sont en lecture seule. Je crains que ce soit un peu plus compliqué que vous ne le pensez.
Si vous ne créez que des instances User avec un formulaire, vous pouvez définir un ModelForm personnalisé qui applique ce comportement :
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
def clean_email(self):
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).exists():
raise forms.ValidationError(u'Email addresses must be unique.')
return email
Il suffit ensuite d'utiliser ce formulaire chaque fois que vous avez besoin de créer un nouvel utilisateur.
BTW, vous pouvez utiliser Model._meta.get_field('field_name')
pour obtenir les champs par nom, plutôt que par position. Ainsi, par exemple :
# The following lines are equivalent
User._meta.fields[4]
User._meta.get_field('email')
UPDATE
La documentation de Django recommande d'utiliser l'option clean
pour toutes les validations couvrant plusieurs champs de formulaire, car elle est appelée après toutes les validations de l'utilisateur. <FIELD>.clean
et <FIELD>_clean
méthodes. Cela signifie que vous pouvez (en grande partie) compter sur le fait que la valeur du champ est présente dans le fichier cleaned_data
de l'intérieur clean
.
Puisque les champs du formulaire sont validés dans l'ordre où ils sont déclarés, je pense qu'il n'y a pas de problème à placer occasionnellement la validation multi-champs dans un fichier de type <FIELD>_clean
pour autant que le champ en question apparaisse après tous les autres champs dont il dépend. Je fais cela pour que toute erreur de validation soit associée au champ lui-même, plutôt qu'au formulaire.