AttributeError: объект 'str' не имеет атрибута 'ValidationError' Django

Я пытаюсь создать метод Views.py, в котором я проверяю, существует ли уже email в базе данных. Это работает для имени пользователя, но не работает для электронной почты или токенов. Как это можно сделать? Спасибо!

@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")

Выдает AttributeError: 'str' object has no attribute 'ValidationError'

Рассмотрите возможность переноса этих проверок в 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):
        ...

Источник: https://docs.djangoproject.com/en/3.2/ref/forms/validation/#cleaning-a-specific-field-attribute


Вы уверены, что это работает для username? AFAIK, мы должны поднимать ValidationError просто как объект исключения.

Мы не должны ожидать, что любое значение из формы вызовет это исключение.

from django.core.exceptions import ValidationError

if User.objects.filter(email=email).exists():
    raise ValidationError("Este Email ya está en uso")

Вы не можете использовать raise email.ValidationError(…). email - это strинг, а у строки нет атрибута ValidationError. Это также нелогично, поскольку переменная email не содержит слова email.

Ваше имя пользователя также не проверяется: это делает сериализатор, и сериализатор просто ошибается на этом, потому что поле username модели User требует, чтобы username было уникальным. Поэтому сериализатор подтвердит это.

Вариант 1: проверка сериализатором

Вы можете реализовать логику и для электронного письма. Например, определив собственную модель или добавив UniqueValidator [DRF-doc] к полю сериализации email:

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())]
            }
        }

Теперь сериализатор будет проверять, уникален ли email, и выдавать ошибку в противном случае. Таким образом, вам следует не делать валидацию в представлении, это относится к уровню сериализации.

Вариант 2: Указание уникальности для поля электронной почты

Если вы определили свою собственную модель пользователя, вы можете сделать поле email также уникальным, тогда модель пользователя будет выглядеть следующим образом:

from django.db import models
from django.contrib.auth.models import AbstractUser

class SignUpDetails(AbstractUser):
    email = models.EmailField(
        _('email address')
        unique=True
    )
    # …
Вернуться на верх