James Huang
James Huang

Reputation: 876

Django Rest Framework specify that email must be unique

Here's a serializer for registering a user.

class RegisterSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password')
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User.objects.create_user(validated_data['username'], validated_data['email'], validated_data['password'])

        return user

Here's the api view:

class RegisterView(generics.GenericAPIView):
    serializer_class = RegisterSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        return Response({
        "user": UserSerializer(user, context=self.get_serializer_context()).data,
        # "token": AuthToken.objects.create(user)[1]
        })

On the api view, if I try to pass in a name that is exactly the same as an existing name, it will say that it already exists. However, I can still make the emails the same which I don't want. Is there a way to get it so that I can also tell DRF that I would like the email to have to be unique as well?

Upvotes: 2

Views: 1851

Answers (2)

Yogesh Bhandari
Yogesh Bhandari

Reputation: 470

Since you are using the ModelSerializer I think you can achieve it by having emails as unique field in the model itself and the serializer will handle the validation part for you.

Upvotes: 1

Scratch'N'Purr
Scratch'N'Purr

Reputation: 10409

There are 2 options:

  1. Enforcing the unique criterion on the serializer level:
from rest_framework import serializers
from rest_framework.validators import UniqueValidator


class RegisterSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(
        validators=[UniqueValidator(queryset=User.objects.all())]
    )  # recommend using `get_user_model`

    class Meta:
        model = User  # recommend using `get_user_model`
        ...

    ...
  1. Using a custom User model that enforces the unique criterion on the model level. More details here:
from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    email = models.EmailField(unique=True)

Note: The 2nd option also requires making changes to the settings and potentially other areas of the code if you reference the User model directly in your other models. If you are directly using User in other areas of your code, please take a look at using get_user_model.

Upvotes: 3

Related Questions