序列化程序字段验证以及如何检查值是否存在?
Serializer field validation and how to check if value exist?
我有 2 个模型,User
和 UserProfile
。 UserProfile
型号有 OneToOneField
和 User
型号。在这里,我试图在一个请求中更新这两个模型。
请求载荷:
{'email': ['xxx@gmail.com'], 'first_name': ['Nalin'], 'last_name': ['Dobhal'],}
我已经为这两个模型创建了序列化程序。
serializers.py
class UserAccountSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False, read_only=True)
mobile = serializers.IntegerField(read_only=True)
email = serializers.EmailField(required=False, read_only=False)
username = serializers.CharField(read_only=True)
class Meta:
model = User
fields = ("id", "mobile", 'email', "username",)
class UserProfileSerializer(serializers.ModelSerializer):
user = UserAccountSerializer(required=False, read_only=False)
# other fields
class Meta:
model = UserProfile
fields = ("user", # other fields)
def update(self, instance, validated_data):
# validated data doesn't have email here, that's why getting value from self.initial_data
if self.initial_data.get("email"):
instance.user.email = self.initial_data.get("email")
instance.user.save()
instance.save()
return instance
views.py
class UserAccountSettingsAPI(generics.RetrieveUpdateAPIView):
http_method_names = ["options", "get", "put", "patch"]
permission_classes = (IsAuthenticated,)
authentication_classes = (TokenAuthentication,)
serializer_class = UserProfileSerializer
def get(self, request, *args, **kwargs):
# some processing
def update(self, request, *args, **kwargs):
profile = UserProfile.objects.select_related("user").get(user_id=request.user.id)
serializer = self.get_serializer(profile, data=request.data)
if serializer.is_valid(raise_exception=False):
serializer.save()
# some other processing only to set key value for context.
return Response(context)
我想在更新用户的电子邮件之前执行一些验证。所以我的问题是在哪里执行验证?有没有更好的方法来做到这一点?我试图在 UserAccountSerializer
中添加 def validate_email(self, email):
但它没有被执行。所以我想确保电子邮件不属于另一个用户,如果电子邮件存在,我想向客户端发送一些自定义错误消息。
我删除了不必要的代码。
尝试添加此代码
在视图中创建或更新
if User.objects.filter(email=self.request.data['email']).exists():
return Response({"error": "This email id already exists."})
我假设您希望 email
是独一无二的。然后你应该添加 unique=True
到你的用户模型的电子邮件字段。
class YourUserModel(AbstractUser):
email = models.EmailField(unique=True)
将电子邮件设为唯一字段后,您的数据库将不允许添加具有相同电子邮件的另一个条目,这将引发 IntegrityError
。您可以捕获此错误并 return 向您的用户发送更好的错误消息。像这样:
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)
您可以尝试提出 ValidationError
,它是 serializers
库的一部分:
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
或者,如果您 unique=True
到 email
字段,它会引发 IntegrityError
,因此您不需要做任何进一步的检查。您只需捕获错误并自行处理即可。
我有 2 个模型,User
和 UserProfile
。 UserProfile
型号有 OneToOneField
和 User
型号。在这里,我试图在一个请求中更新这两个模型。
请求载荷:
{'email': ['xxx@gmail.com'], 'first_name': ['Nalin'], 'last_name': ['Dobhal'],}
我已经为这两个模型创建了序列化程序。
serializers.py
class UserAccountSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False, read_only=True)
mobile = serializers.IntegerField(read_only=True)
email = serializers.EmailField(required=False, read_only=False)
username = serializers.CharField(read_only=True)
class Meta:
model = User
fields = ("id", "mobile", 'email', "username",)
class UserProfileSerializer(serializers.ModelSerializer):
user = UserAccountSerializer(required=False, read_only=False)
# other fields
class Meta:
model = UserProfile
fields = ("user", # other fields)
def update(self, instance, validated_data):
# validated data doesn't have email here, that's why getting value from self.initial_data
if self.initial_data.get("email"):
instance.user.email = self.initial_data.get("email")
instance.user.save()
instance.save()
return instance
views.py
class UserAccountSettingsAPI(generics.RetrieveUpdateAPIView):
http_method_names = ["options", "get", "put", "patch"]
permission_classes = (IsAuthenticated,)
authentication_classes = (TokenAuthentication,)
serializer_class = UserProfileSerializer
def get(self, request, *args, **kwargs):
# some processing
def update(self, request, *args, **kwargs):
profile = UserProfile.objects.select_related("user").get(user_id=request.user.id)
serializer = self.get_serializer(profile, data=request.data)
if serializer.is_valid(raise_exception=False):
serializer.save()
# some other processing only to set key value for context.
return Response(context)
我想在更新用户的电子邮件之前执行一些验证。所以我的问题是在哪里执行验证?有没有更好的方法来做到这一点?我试图在 UserAccountSerializer
中添加 def validate_email(self, email):
但它没有被执行。所以我想确保电子邮件不属于另一个用户,如果电子邮件存在,我想向客户端发送一些自定义错误消息。
我删除了不必要的代码。
尝试添加此代码
在视图中创建或更新
if User.objects.filter(email=self.request.data['email']).exists():
return Response({"error": "This email id already exists."})
我假设您希望 email
是独一无二的。然后你应该添加 unique=True
到你的用户模型的电子邮件字段。
class YourUserModel(AbstractUser):
email = models.EmailField(unique=True)
将电子邮件设为唯一字段后,您的数据库将不允许添加具有相同电子邮件的另一个条目,这将引发 IntegrityError
。您可以捕获此错误并 return 向您的用户发送更好的错误消息。像这样:
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)
您可以尝试提出 ValidationError
,它是 serializers
库的一部分:
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
或者,如果您 unique=True
到 email
字段,它会引发 IntegrityError
,因此您不需要做任何进一步的检查。您只需捕获错误并自行处理即可。