Обновление данных с помощью RetrieveUpdateAPIView - получение проверенных данных из сериализатора - PullRequest
0 голосов
/ 10 мая 2018

Я хотел бы обновить определенные свойства пользователя (скажем, имя и фамилия) мой объект json через запрос PUT будет выглядеть так

   {
"user" :    {   
             "first_name": "Jack",   
             "last_name": "shnider",
             "password":"admin123" 
             "email" : "foo@google.com"
             },

"employee_zip" : 12345
}

Вот так выглядит мой вид (я бы хотел обновить существующие поля до этих новых полей).

Это сериализатор

  class Serializer_UpdateUser(ModelSerializer):
    class Meta:
        model = User
        fields = ('first_name','last_name','password')

class Serializer_UpdateEmployer(ModelSerializer):
    user = Serializer_UpdateUser()
    class Meta:
        model = modelEmployer
        fields = [
            'user',
            'employer_zip',
        ]

Это вид:

class UpdateProfile_RetrieveUpdateAPIView(RetrieveUpdateAPIView):
    queryset = modelEmployer.objects.all()
    serializer_class = Serializer_UpdateEmployer
    lookup_field = 'user__email'
    permission_classes = [permissions.AllowAny]

    def update(self, request, *args, **kwargs):
        instance = self.get_object() #------>I have the object that I would like to update
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True) #--->Success

Теперь я хотел бы получить проверенные поля (json содержит только те поля, которые были обновлены). Я знаю, если я сделаю что-то подобное

serializer.save

Я бы вернул модельEmployer, но вместо этого я получил эту ошибку

AssertionError at /api/employer/update_profile/employerA@gmail.com/ The `.update()` method does not support writable nested fields by default. Write an explicit `.update()` method for serializer `Employer.api.serializers.Serializer_ListEmployer`, or set `read_only=True` on nested serializer fields. Request Method: 

У меня два вопроса

1-Почему сбой сохранения?

2-Как я могу получить проверенные данные из вышеуказанного сериализатора?

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Я думаю, drf-writable-nested может помочь вам обновить вложенные данные.

В вашем случае:

from django.contrib.auth import password_validation

  class Serializer_UpdateUser(ModelSerializer):

    def update(self, instance, validated_data):
        password = validated_data.pop('password', None)
        super(Serializer_UpdateUser, self).update(instance, validated_data)
        if password is not None:
            instance.set_password(password)
            instance.save()
        return instance

    def validate_password(self, value):
        password_validation.validate_password(value)
        return value

    class Meta:
        model = User
        fields = ('first_name','last_name','password')

class Serializer_UpdateEmployer(WritableNestedModelSerializer):
    user = Serializer_UpdateUser()
    class Meta:
        model = modelEmployer
        fields = [
            'user',
            'employer_zip',
        ]

Обратите внимание, вам нужна специальная обработка password поле.

0 голосов
/ 10 мая 2018

Сохранение не выполнено, поскольку django-rest-framework по умолчанию не работает с вложенными сериализаторами.

из документов django-rest-framework :

По умолчанию вложенные сериализаторы только для чтения. Если вы хотите поддерживать операции записи для вложенного поле сериализатора, которое вам нужно будет создать create () и / или update () методы для того, чтобы явно указать, как дочерние отношения должен быть сохранен.

Вы должны переопределить метод update в сериализаторе, чтобы разрешить такое поведение:

class Serializer_UpdateEmployer(ModelSerializer):
    user = Serializer_UpdateUser()
    class Meta:
        model = modelEmployer
        fields = [
            'user',
            'employer_zip',
        ]

    def update(self, instance, validated_data):
        user_data = validated_data.pop('user', {})
        user_serializer = Serializer_UpdateUser(instance.user, data=user_data)
        user_serializer.save()
        return instance

Другое решение заключается в использовании drf-writable-nested . Это автоматически делает ваши вложенные сериализаторы обновляемыми.

from drf_writable_nested import WritableNestedModelSerializer

class Serializer_UpdateEmployer(WritableNestedModelSerializer):
    user = Serializer_UpdateUser()
    class Meta:
        model = modelEmployer
        fields = [
            'user',
            'employer_zip',
        ]
...