How can I make a Django User email unique when a user is signing up?
forms.py
class SignUpForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
I'm using the from django.contrib.auth.models User. Do I need to override the User in the model. Currently the model doesn't make a reference to User.
views.py
class SignUp(generic.CreateView):
form_class = SignUpForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
If you want to use django's default authentication backend you cannot make username non unique. You will have to implement a class with get_user(user_id) and authenticate(request, **credentials) methods for a custom backend.
EmailField in Django Forms is a string field, for input of Emails. It is used for taking text inputs from the user. The default widget for this input is EmailInput. It uses MaxLengthValidator and MinLengthValidator if max_length and min_length are provided.
In order to make our email field required in our database, we need to define a custom user model. Let's do it inside our accounts application. It's also important to make our email field unique. Then, add the AUTH_USER_MODEL variable in our settings.py to tell Django we're going to use a custom model for our users.
The best answer is to use CustomUser
by subclassing the AbstractUser
and put the unique email address there. For example:
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
and update the settings with AUTH_USER_MODEL="app.CustomUser"
.
But if its not necessary for you to store the unique email in Database or maybe not use it as username field, then you can update the form's clean
method to put a validation. For example:
from django.core.exceptions import ValidationError
class YourForm(UserCreationForm):
def clean(self):
email = self.cleaned_data.get('email')
if User.objects.filter(email=email).exists():
raise ValidationError("Email exists")
return self.cleaned_data
If you are in mid project, then you can follow the documentation on how to change migration, in short which is to:
__init__.py
)django_migrations
python manage.py makemigrations
python manage.py migrate --fake
db_table
, make other changes to the custom model, generate migrations, apply themBut if you are just starting, then delete the DB and migrations files in migration directory except for __init__.py
. Then create a new DB, create new set of migrations by python manage.py makemigrations
and apply migrations by python manage.py migrate
.
And for references in other models, you can reference them to settings.AUTH_USER_MODEL
to avoid any future problems. For example:
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
It will automatically reference to the current User Model.
Here is a working code
Use the below code snippets in any of your models.py
models.py
from django.contrib.auth.models import User
User._meta.get_field('email')._unique = True
django version : 3.0.2
Reference : Django auth.user with unique email
There is a great example of this in Django's docs - https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#a-full-example.
You have to declare the email field in your AbstractBaseUser
model as unique=True
.
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With