Как разрешить обновление только 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 намного чище в ваших представлениях, согласно документации.