Field-level validation / UniqueValidator interaction

24 views
Skip to first unread message

jeremy...@m4x.org

unread,
Dec 16, 2020, 8:25:34 AM12/16/20
to Django REST framework
Hi!

I have encountered a situation where a serializer's field-level validation (i.e. writing a validate_FOO method) and the UniqueValidator inherited from the model interact in an unexpected way.

The use-case here is serializing "user" objects, where I wish to:
  • ensure e-mail addresses are coerced to lowercase
  • ensure e-mail addresses are unique across users
Here is a cut-down version of the User model:

class User(AbstractBaseUser):
    email = models.EmailField(max_length=254, unique=True)

And the corresponding serializer:

class UserSerializer(serializers.ModelSerializer):
    def validate_email(self, value):
        return value.lower()

At first glance, this does the job : a mixed-case email gets coerced to lowercase, and a duplicate email is rejected with a validation error. However a closer look shows things are not working as expected: if the submitted e-mail differs only in case with an existing e-mail, no validation error occurs and instead an exception is thrown due to a violation of a database-level constraint.

The reason is that validators are executed *before* field-level validation methods. This means that if a field-level validation method performs any transformation on the value, the validators will have run on the "wrong" data (i.e before transformation). Does anyone have any guidance on how to approach this?

Cheers,
Jeremy
Reply all
Reply to author
Forward
0 new messages