【问题标题】:AttributeError: 'str' object has no attribute 'ValidationError' DjangoAttributeError:“str”对象没有属性“ValidationError”Django
【发布时间】:2021-11-12 11:11:59
【问题描述】:

我正在尝试创建 Views.py 方法,用于检查电子邮件是否已存在于数据库中。它适用于用户名,但不适用于电子邮件或令牌。使这成为可能的方法是什么?谢谢!

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

这是序列化程序:

class SignUpDetailsForm(serializers.ModelSerializer):
    class Meta:
        model = SignUpDetails
        fields = (
            'first_name',
            'last_name',
            'email',
            'username',
            'password',
        )

它生成 AttributeError: 'str' object has no attribute 'ValidationError'

【问题讨论】:

  • Python 明确表示 email 对象是 'str' 对象没有属性 'ValidationError' 。
  • @madzohan 好的,用户名也是一个字符串,虽然它没有得到这个错误。
  • 不可能是真的 :) 使用 a= 'ololo' 运行 python; a.ValidationError

标签: javascript python django django-rest-framework


【解决方案1】:

您不能使用raise <s>email.</s>ValidationError(…)。 email 是 string,字符串没有 ValidationError 属性。这也是无意义的,因为变量 email 不包含单词 email。

您的用户名也没有经过验证:这是由序列化程序完成的,而序列化程序只会在此错误,因为User 模型的username 字段要求username 是唯一的。因此,序列化程序将对此进行验证。

选项 1:由序列化程序验证

您也可以为电子邮件实现逻辑。例如,通过定义您自己的模型,或在电子邮件序列化字段中添加 UniqueValidator [DRF-doc]:

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

现在序列化程序将检查电子邮件是否是唯一的,否则会引发错误。因此,您应该不在视图中进行验证,这属于序列化层。

选项 2:指定电子邮件字段的唯一性

如果您定义了自己的用户模型,您也可以使电子邮件字段唯一,那么用户模型如下所示:

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

class SignUpDetails(AbstractUser):
    email = models.EmailField(
        _('email address')
        unique=True
    )
    # …

【讨论】:

  • 好的,最简单的方法是创建我自己的用户注册模型并将电子邮件设置为唯一,对吧?
  • @IvanStepanchuk:SignUpDetails 不是你的用户模型吗?如果你没有,你可以简单地添加一个UniqueValidator,就像选项 1 一样。因此有两种方法可以解决这个问题。
【解决方案2】:

考虑将这些检查迁移到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

【讨论】:

  • 我已经尝试过了,但我的序列化程序甚至都没有看到。它只是发布而不会触发任何错误。
【解决方案3】:

您确定它适用于username 吗? AFAIK,我们应该将 ValidationError 作为异常对象引发。

我们不应该期望表单中的任何值都会引发此异常。

from django.core.exceptions import ValidationError

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

【讨论】:

  • 它确实与用户一起工作,表单收到该用户名已经存在的消息。但是当涉及到电子邮件时,这就是出现此 str 错误的地方。您给出的想法返回此错误:第 33 行,在 send_user_details raise ValidationError("Este Email ya está en uso") django.core.exceptions.ValidationError: ['Este Email ya está en uso']
  • 当我将它与用户名一起使用时,它会显示“用户名:具有该用户名的用户已经存在。”并且它没有显示我放入 ValidationError 的字符串消息。当与电子邮件一起使用时,它会返回上述错误。
  • @IvanStepanchuk:该错误是由 serializer 产生的,而不是由您的错误处理产生的。
  • @WillemVanOnsem 好的,在这种情况下可能是什么问题?根据序列化程序,用户名和电子邮件接受相同的处理,虽然它可以与用户名一起使用但不能与电子邮件一起使用?
  • @IvanStepanchuk:因为标准用户模型在username 上具有unique=True 约束,但在email 字段上没有。因此,构造的序列化程序将验证用户名的唯一性,而不是电子邮件的唯一性。但是,您可以使 email 字段对您的模型是唯一的
猜你喜欢
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-06
  • 1970-01-01
  • 2021-07-05
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多