Как разрешить обновление только 1 поля?

Делаю приложение, в котором пользователь может загружать фотографии, каждая фотография имеет пользователя, изображение, описание и другие поля. Когда пользователь создает новую фотографию, изображение обязательно, но когда пользователь хочет обновить ее, можно изменить только описание. Я застрял на этом, сначала попробовал с update (put), но это явно не тот метод, который нужно использовать, теперь пытаюсь с partial_update, но не могу добиться нужного результата.

Вот что у меня есть сейчас, это дает мне ошибку: TypeError: Object of type Photo is not JSON serializable.

Возможно, это совершенно неправильный способ сделать это.

Вид:

class PhotoViewSet(mixins.RetrieveModelMixin,
               mixins.CreateModelMixin,
               mixins.UpdateModelMixin,
               mixins.DestroyModelMixin,
               viewsets.GenericViewSet):
""" PhotoViewSet

Handle upload (create) and delete of photos.
"""

queryset = Photo.objects.all()
serializer_class = PhotoModelSerializer

def perfom_create(self, serializer):
    """ Upload a new photo. """
    serializer.save()

def perform_destroy(self, instance):
    """ Delete a photo. """
    return super().perform_destroy(instance)

def retrieve(self, request, *args, **kwargs):
    """ Retrieve photo information. """
    response = super(PhotoViewSet, self).retrieve(request, *args, **kwargs)
    data = {
        'photo': response.data,
    }
    response.data = data
    return response

def partial_update(self, request, pk=None):
    serializer = UpdateDescriptionSerializer(data=request.data, partial=True)
    serializer.is_valid(raise_exception=True)
    data = serializer.save()
    return Response(data=data, status=status.HTTP_202_ACCEPTED)

serializer:

class UpdateDescriptionSerializer(serializers.ModelSerializer):
""" Update description serializer. """

description = serializers.CharField(max_length=255)

class Meta:
    """ Meta class. """

    model = Photo
    fields = ('description',)

Вам следует передать экземпляр, который вы хотите обновить. Кроме того, вы должны возвращать не результат метода .save(), а данные сериализатора, так:

def partial_update(self, request, pk=None):
    instance = self.get_object()
    serializer = UpdateDescriptionSerializer(
        instance,
        data=request.data,
        partial=True
    )
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(data=serializer.data, status=status.HTTP_202_ACCEPTED)

Если вы хотите вернуть все детали обновленного элемента, вы можете работать с другим сериализатором, который будет создавать данные для ответа, так:

def partial_update(self, request, pk=None):
    instance = self.get_object()
    serializer = UpdateDescriptionSerializer(
        instance,
        data=request.data,
        partial=True
    )
    serializer.is_valid(raise_exception=True)
    serializer.save()
    serializer2 = PhotoModelSerializer(instance)
    return Response(data=serializer2.data, status=status.HTTP_202_ACCEPTED)

Вы должны использовать 2 разных сериализатора, один из которых предназначен для обновления объекта, например PhotoSerializer и UpdatePhotoSerializer. Я бы предложил переопределить метод get_serializer_class() следующим образом:

def get_serializer_class(self):
    if self.request.method == "PATCH":  # add PUT too if you wish
        return UpdatePhotoSerializer

    return PhotoSerializer

Еще один совет, использование generic views намного чище в ваших представлениях, согласно документации.

Вернуться на верх