Единый API обновления и удаления для двух моделей, связанных отношением OneToOne в Django Rest Framework

Я много искал здесь и, вероятно, исчерпал все ответы, и все еще не нашел решения моей конкретной проблемы, которая заключается в том, чтобы сделать API, который обновляет/удаляет из обеих моделей, и я получаю следующую ошибку:

The .update()method does not support writable nested fields by default. Write an explicit.update()method for serializeruser_profile.serializers.UserSerializer, or set read_only=True on nested serializer fields.

В данном конкретном случае это происходит, когда я пытаюсь обновить поле из модели user_profile

Я разделил свой проект Django на несколько приложений/папок, каждая модель находится в своей собственной папке.

У меня есть приложение user и приложение user_profile каждое со своими собственными моделями.

модель пользователя - это, по сути, AbstractUser, сидящий в своем собственном приложении

модель user_profile выглядит следующим образом:

class UserProfile(models.Model): user = models.OneToOneField(to=User, on_delete=models.CASCADE, related_name='userprofile') location = models.CharField(blank=True, max_length=30) created_time = models.DateTimeField(auto_now_add=True) updated_time = models.DateTimeField(auto_now=True)

Сериализаторы следующие:

`class UserProfileCrudSerializer(serializers.ModelSerializer): class Meta: модель = UserProfile поля = ('location', 'created_time', 'updated_time')

class UserSerializer(serializers.ModelSerializer): profile = UserProfileCrudSerializer(source='userprofile', many=False)

class Meta:
    model = User
    fields = ('username', 'email', 'first_name', 'last_name', 'profile')

    def update(self, instance, validated_data):
        userprofile_serializer = self.fields['profile']
        userprofile_instance = instance.userprofile
        userprofile_data = validated_data.pop('userprofile', {})

        userprofile_serializer.update(userprofile_instance, userprofile_data)

        instance = super().update(instance, validated_data)
        return instance`

а мое мнение таково:

`class RetrieveUpdateView(RetrieveUpdateAPIView): serializer_class = UserSerializer queryset = User.objects.all()

def get_object(self):
    return self.request.user`

Когда я делаю GET, я получаю следующий ответ без каких-либо проблем:

{ "username": "blue", "email": "bluebear@bluebear.com", "first_name": "Blue", "last_name": "Bear", "profile": { "location": "London", "created_time": "2023-02-03T00:39:15.149924Z", "updated_time": "2023-02-03T00:39:15.149924Z" } }

и я делаю запрос на исправление следующим образом:

{ "profile": { "location": "Paris" } }

Сейчас у меня нет проблем с обновлением имени пользователя, email, first_name и last_name, которые приходят из AbstractUser, но я получаю вышеуказанную ошибку, когда пытаюсь исправить местоположение, которое находится в модели UserProfile.

Я просмотрел множество подобных решений в Интернете, но ни одно из них не относится к моей конкретной ситуации.

Метод .update() по умолчанию не поддерживает записываемые вложенные поля. Напишите явный метод .update() для serializeruser_profile.serializers.UserSerializer, или установите read_only=True для вложенных полей сериализатора.

.

В сообщении уже показано, вам нужно явно написать метод обновления для записываемого вложенного сериализатора, который документирован здесь https://www.django-rest-framework.org/topics/writable-nested-serializers/ или вы можете использовать другой модуль, который также упоминается в документации https://github.com/beda-software/drf-writable-nested.

Ваш подход уже правильный, но в вашем коде есть опечатка и неправильный отступ:

class UserSerializer(serializers.ModelSerializer):
    profile = UserProfileCrudSerializer(source='userprofile', many=False)

    class Meta:
        model = User
        fields = ('username', 'email', 'first_name', 'last_name', 'profile')

    def update(self, instance, validated_data):
        # update is a method of serializer not serializer.Meta
        userprofile_serializer = self.fields['profile']
        userprofile_instance = instance.userprofile
        # should be 'profile' here instead of 'userprofile' as you defined in serializer
        userprofile_data = validated_data.pop('profile', {})

        userprofile_serializer.update(userprofile_instance, userprofile_data)

        instance = super().update(instance, validated_data)
        return instance
Вернуться на верх