Поле сериализатора, предназначенное только для Django rest framework

#python #django #django-rest-framework

#python #django #django-rest-framework

Вопрос:

У меня есть модель Django, которая служит описанием запроса. Оно создано для отправки запроса клиентом REST, служит для записи текущего статуса задач и записи исторических запросов, полученных клиентами.

В этой модели есть несколько полей, которые используются для точной настройки и управления запрошенной задачей (скажем, целевым объектом и типом действия). Очевидно, я бы хотел, чтобы клиент управлял этими полями при создании объекта, но не после (вы не можете изменить объект после запуска задачи).

Я надеялся на что-то похожее на serializers.ReadOnlyField , поэтому у меня могло бы быть что-то похожее на это:

 class TaskSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    task_id = serializers.ReadOnlyField()
    target_object = serializers.CreateOnlyField()
  

но не смог найти его в документации или Google.

Ответ №1:

Просто чтобы расширить ответ Wim, это способ выбрать другой сериализатор на основе метода входящего запроса:

 class RequestViewSet(viewsets.ModelViewSet): 
    serializer_class = RequestModelSerializer 
    model = Request 

    def get_serializer_class(self): 
        serializer_class = self.serializer_class 
        if self.request.method == 'POST': 
            serializer_class = SerializerWithoutCertainFields 
        return serializer_class
  

Ответ №2:

Ответ @fabio.sussetto направил меня на правильный путь. Я думаю, что мой ответ немного красивее; я не указываю сериализатор в классе напрямую, а только в get_serializer_class() . Кроме того, я переключаю его не на основе типа HTTP (т. Е. POST ), а скорее на основе действия, update которое я считаю более декларативным.

 class RequestViewSet(viewsets.ModelViewSet): 
    model = Request 

    def get_serializer_class(self): 
        if self.action == 'update': 
            return serializer_class = SerializerWithoutCertainFields 
        return RequestModelSerializer
  

Ответ №3:

Этого можно достичь с помощью одного сериализатора с помощью to_internal_value метода

 class TaskSerializer(serializers.ModelSerializer):
    # Field settings here

    def to_internal_value(self, data):
        data = super().to_internal_value(data)
        # Remove target_object if serializer is updating object
        if self.instance:
            data.pop('target_object', None)
        return data

    class Meta:
        model = Task
        fields = ('owner', 'task_id', 'target_object')
  

Ответ №4:

также может быть выполнено с помощью комбинации required=False и удаления значения поля при обновлении, как в этом примере:

 class SectionSerializer(serializers.ModelSerializer):

    # do not require field lesson when updating
    lesson = serializers.PrimaryKeyRelatedField(queryset=Lesson.objects.all(), required=False)

    # do not allow changing the lesson field
    def update(self, instance, validated_data):
        validated_data.pop("lesson", None)
        return super().update(instance, validated_data)