I need to patch the standard User model of contrib.auth
by ensuring the email field entry is unique:
User._meta.fields[4].unique = True
<
Caution: The code below was written for an older version of Django (before Custom User Models were introduced). It contains a race condition, and should only be used with a Transaction Isolation Level of
SERIALIZABLE
and request-scoped transactions.
Your code won't work, as the attributes of field instances are read-only. I fear it might be a wee bit more complicated than you're thinking.
If you'll only ever create User instances with a form, you can define a custom ModelForm that enforces this behavior:
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
Then just use this form wherever you need to create a new user.
BTW, you can use Model._meta.get_field('field_name')
to get fields by name, rather than by position. So for example:
# The following lines are equivalent
User._meta.fields[4]
User._meta.get_field('email')
The Django documentation recommends you use the clean
method for all validation that spans multiple form fields, because it's called after all the
and
methods. This means that you can (mostly) rely on the field's value being present in cleaned_data
from within clean
.
Since the form fields are validated in the order they're declared, I think it's okay to occasionally place multi-field validation in a
method, so long as the field in question appears after all other fields it depends on. I do this so any validation errors are associated with the field itself, rather than with the form.