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.
- 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