I am trying to create Views.py method where I check if the email already exists in the database. It worked for username but it is not working for emails or tokens. What would be the way to make that possible? Thank you!
@api_view(['POST'])
def send_user_details(request):
if request.method == "POST":
serializer = SignUpDetailsForm(data=request.data)
if serializer.is_valid():
email = serializer.validated_data['email']
username = serializer.validated_data['username']
password = serializer.validated_data['password']
if User.objects.filter(email=email).exists():
raise email.ValidationError("Este Email ya está en uso")
if User.objects.filter(username=username).exists():
raise username.ValidationError("Este Usuario ya está en uso")
This is the serializer:
class SignUpDetailsForm(serializers.ModelSerializer):
class Meta:
model = SignUpDetails
fields = (
'first_name',
'last_name',
'email',
'username',
'password',
)
It generates AttributeError: 'str' object has no attribute 'ValidationError'
You can not use raise . email.ValidationError(…)email is a string, and a string has no ValidationError attribute. It is also non-sensical, since the variable email does not contain the word email.
Your username is not validated either: that is done by the serializer, and the serializer simply errors on this because the username field of the User model requires the username to be unique. Therefore the serializer will validate this.
You can implement logic for the email as well. For example by defining your own model, or by adding a UniqueValidator [DRF-doc] to the email serialization field:
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
class SignUpDetailsForm(serializers.ModelSerializer):
class Meta:
model = SignUpDetails
fields = (
'first_name',
'last_name',
'email',
'username',
'password',
)
extra_kwargs = {
'email': {
'validators': [UniqueValidator(queryset=SignUpDetails.objects.all())]
}
}
Now the serializer will thus check if the email is unique, and raise an error otherwise. You thus should not do validation in the view, this belongs in the serialization layer.
If you defined your own user model, you can make the email field unique as well, then the user model looks like:
from django.db import models
from django.contrib.auth.models import AbstractUser
class SignUpDetails(AbstractUser):
email = models.EmailField(
_('email address')
unique=True
)
# …Consider migrating these checks to the SignUpDetailForm:
from django import forms
from django.core.exceptions import ValidationError
class SignUpDetailForm(forms.Form):
def clean_email(self):
email = self.cleaned_data['email']
if User.objects.filter(email=email).exists():
raise ValidationError('Este Email ya está en uso')
def clean_username(self):
...
Source: https://docs.djangoproject.com/en/3.2/ref/forms/validation/#cleaning-a-specific-field-attribute
Are you sure it works for username?
AFAIK, we should raise ValidationError just as an object of exception.
We should not expect that any of the value from form will raise this exception.
from django.core.exceptions import ValidationError
if User.objects.filter(email=email).exists():
raise ValidationError("Este Email ya está en uso")