Python 序列化程序字段验证以及如何检查值是否存在?

Python 序列化程序字段验证以及如何检查值是否存在?,python,django,django-rest-framework,django-serializer,Python,Django,Django Rest Framework,Django Serializer,我有两种型号,User和UserProfileUserProfile模型具有OneToOneField和User模型。在这里,我试图在一个请求中更新这两个模型 请求有效负载: {'email': ['xxx@gmail.com'], 'first_name': ['Nalin'], 'last_name': ['Dobhal'],} 我已经为这两个模型创建了序列化程序 序列化程序.py class UserAccountSerializer(serializers.ModelSerialize

我有两种型号,
User
UserProfile
UserProfile
模型具有
OneToOneField
User
模型。在这里,我试图在一个请求中更新这两个模型

请求有效负载:

{'email': ['xxx@gmail.com'], 'first_name': ['Nalin'], 'last_name': ['Dobhal'],}
我已经为这两个模型创建了序列化程序

序列化程序.py

class UserAccountSerializer(serializers.ModelSerializer):
id=序列化程序.IntegerField(必需=False,只读=True)
mobile=serializers.IntegerField(只读=True)
email=serializers.EmailField(必需=False,只读=False)
username=serializers.CharField(只读=True)
类元:
模型=用户
字段=(“id”、“手机”、“电子邮件”、“用户名”)
类UserProfileSerializer(serializers.ModelSerializer):
user=UserAccountSerializer(必需=False,只读=False)
#其他领域
类元:
model=UserProfile
字段=(“用户”、#其他字段)
def更新(自身、实例、已验证的_数据):
#验证数据在这里没有电子邮件,这就是为什么从self.initial\u数据中获取价值
如果自我初始数据获取(“电子邮件”):
instance.user.email=self.initial_data.get(“电子邮件”)
instance.user.save()
save()实例
返回实例
视图.py

class UserAccountSettingsAPI(generics.RetrieveUpdateAppiview):
http_方法_名称=[“选项”、“获取”、“放置”、“修补程序”]
权限\类=(已验证,)
身份验证\类=(令牌身份验证)
serializer\u class=UserProfileSerializer
def get(自我、请求、*args、**kwargs):
#一些加工
def更新(自我、请求、*args、**kwargs):
profile=UserProfile.objects.select\u related(“user”).get(user\u id=request.user.id)
serializer=self.get\u序列化程序(profile,data=request.data)
如果serializer.is_有效(raise_exception=False):
serializer.save()
#某些其他处理仅用于设置上下文的键值。
返回响应(上下文)
我想在更新用户的电子邮件之前执行一些验证。所以我的问题是在哪里进行验证?还有更好的方法吗?我试图在
UserAccountSerializer
中添加
def validate\u电子邮件(self,email):
,但没有执行。所以我想确保电子邮件不属于其他用户,如果电子邮件存在,我想向客户发送一些自定义错误消息。 我已删除了不必要的代码。

请尝试添加此代码

在视图中创建或更新

if User.objects.filter(email=self.request.data['email']).exists():
    return Response({"error": "This email id already exists."})

我假设您希望
电子邮件
是唯一的。然后,您应该将
unique=True
添加到您的用户模型的电子邮件字段中

class YourUserModel(AbstractUser):
    email = models.EmailField(unique=True)
将电子邮件设为唯一字段后,您的数据库将不允许使用同一电子邮件添加其他条目,并将引发
IntegrityError
。您可以捕获此错误并向用户返回更好的错误消息。像这样:

try:
    if serializer.is_valid(raise_exception=False):
        serializer.save()
except IntegrityError:
    return Response(data={'message':'that email is in use'}, status=HTTP_400_BAD_REQUEST)

您可以尝试引发
验证错误
,它是
序列化程序
库的一部分:

from rest_framework import serializers

def update(self, instance, validated_data):
  # If `self.request.data["email"]` works
  if User.objects.filter(email=self.request.data["email"]).exists():
    raise serializers.ValidationError("This email already exists.")

  # If `self.request.data["email"]` doesn't work
  new_email = self.initial_data.get("email"):
  if new_email and User.objects.filter(email=new_email).exists():
    raise serializers.ValidationError("This email already exists.")

  # Save and return the modified instanced

或者,如果您对
email
字段执行
unique=True
,它将引发
IntegrityError
,因此您无需进行任何进一步的检查。您只需捕获错误并自行处理。

这是我尝试的第一件事,但我不知道这是否是正确的方法。谢谢你的回答,但我将等待其他答案。电子邮件字段是唯一的,我也得到integrityerror。但它和另一个答案是一样的,在视图中处理和处理它。谢谢你的回答。谢谢,对已接受的答案进行了很好的补充。