How to make email field unique in model User from contrib.auth in Django


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

Where is best place in code to do that?

I want to avoid using the number fields[4]. It's better to user fields['email'], but fields is not dictionary, only list.

Another idea may be to open a new ticket and upload a patch with new parameter inside


Any suggestions on the most correct way to achieve email address uniqueness in the Django User model?

Best Solution

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


The Django documentation recommends you use the clean method for all validation that spans multiple form fields, because it's called after all the <FIELD>.clean and <FIELD>_clean 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 <FIELD>_clean 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.