Django rest framework обновление поля OneToOne
У меня есть модель User, которая наследуется от AbstractUser и имеет поле email. И модель профиля, которая имеет отношение OneToOne с моделью User
class User(AbstractUser):
email = models.EmailField(unique=True)
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
phone = models.CharField(max_length=13, validators=[phone_regex], unique=True, null=True, blank=True)
birth_date = models.DateField(blank=True, null=True)
about = models.TextField(max_length=2000, blank=True)
def __str__(self):
return f"{self.user.first_name} {self.user.last_name}"
view.py
class ProfileViewSet(ModelViewSet):
....
@action(detail=False, methods=["GET", "PUT"], permission_classes=[IsAuthenticated])
def me(self, request, *args, **kwargs):
profile = Profile.objects.get(user_id=request.user.id)
if request.method == "GET":
serializer = ProfileSerializer(profile)
return Response(serializer.data)
elif request.method == "PUT":
serializer = ProfileSerializer(profile, request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
serializers.py
class ProfileSerializer(serializers.ModelSerializer):
user = CurrentUserSerializer()
def update(self, instance, validated_data):
user_data = validated_data.pop('user')
user_ser = CurrentUserSerializer(instance=instance.user, data=user_data)
if user_ser.is_valid():
user_ser.save()
instance.phone = validated_data.get('phone', instance.phone)
instance.birth_date = validated_data.get('birth_date', instance.birth_date)
instance.about = validated_data.get('about', instance.about)
instance.save()
return instance
class Meta:
model = Profile
fields = [
'id',
'user',
'phone',
'birth_date',
'about',
]
Теперь, когда я пытаюсь обновить профиль пользователя, я получаю статус: 400 Bad Request error
{
"user": {
"email": [
"user with this email already exists."
]
}
}
Использование patch вместо put или partial=True ничего не меняет, я все равно получаю эту ошибку. Что я могу сделать?
Дело в том, что вы создаете новую запись в базе данных, а это не разрешено
class ProfileSerializer(serializers.ModelSerializer):
user = CurrentUserSerializer()
def update(self, instance, validated_data):
user_data = validated_data.pop('user')
try:
user=User.objects.get(pk=instance.user.id)
except User.DoesNotExist:
raise ValidationError("User already exist")
#now with user instance you can save the email or do whatever
you want
user.email = "xyaz@gmail.com")
user.save()
instance.phone = validated_data.get('phone', instance.phone)
instance.birth_date = validated_data.get('birth_date', instance.birth_date)
instance.about = validated_data.get('about', instance.about)
instance.save()
return instance
class Meta:
model = Profile
fields = [
'id',
'user',
'phone',
'birth_date',
'about',
]
Вместо вложенного сериализатора я использовал поля сериализатора, и моя проблема была решена. Я не уверен, хороший ли это подход или нет.
class ProfileSerializer(serializers.ModelSerializer):
email = serializers.EmailField(source='user.email')
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
def update(self, instance, validated_data):
user_data = validated_data.pop('user')
user = instance.user
user_ser = CurrentUserSerializer(instance=user, data=user_data)
if user_ser.is_valid():
user_ser.save()
instance.phone = validated_data.get('phone', instance.phone)
instance.birth_date = validated_data.get('birth_date', instance.birth_date)
instance.about = validated_data.get('about', instance.about)
instance.save()
class Meta:
model = Profile
fields = [
'id',
'email',
'first_name',
'last_name',
'phone',
'birth_date',
'about',
]