Как заставить create и retrieve работать в одном сериализаторе?

У меня несколько запутанная проблема, у меня есть следующие модели


class ModelA(models.Model):
    name = models.CharField(max_length=64)

class ModelB(models.Model):
    model_a = models.ForeignKey(ModelA, on_delete=models.CASCADE)

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

class ModelASerializer(serializers.ModelSerializer):
    class Meta:
        model = ModelA
        fields = '__all__'

class ModelBSerializer(serializers.ModelSerializer):
    terminal = ModelASerializer(read_only=True)
    class Meta:
        model = ModelB
        fields = '__all__'

когда я хочу создать объект ModelB, включающий модель_a_id, он имеет 2 ответа в зависимости от того, ставлю ли я read_only=True или False

Я хотел бы, чтобы при попытке создания через POST в объекте ModelB мне нужно было только отправить mode_a_id, но в то же время, когда я делаю GET, он возвращает сериализованные данные ModelASerializer в поле model_a. Если я ставлю read_only = True, то работает только получение сериализованных данных в GET, но через POST я не могу присвоить идентификатор model_a

в случае read_only=False я не могу присвоить id этому объекту, так как он запрашивает словарь, я представляю, что нужно создать новый ModelA объект, но я хочу присвоить только тот, который уже существует.

Решением может быть размещение сериализатора с другим именем переменной, но мне бы очень хотелось, чтобы оно было одинаковым и для POST, и для GET.

Просто переопределите to_representation() метод вашего ModelBSerializer следующим образом.

class ModelASerializer(serializers.ModelSerializer):
    class Meta:
        model = ModelA
        fields = '__all__'

class ModelBSerializer(serializers.ModelSerializer):
    terminal = ModelASerializer(read_only=True)
    class Meta:
        model = ModelB
        fields = '__all__'
    
    def to_representation(self, instance):
        pre_represented_data = super().to_representation(instance)
        pre_represented_data['model_a'] = ModelASerializer(instance.model_a).data
        return pre_represented_data

А если вы серьезно не хотите, чтобы id из ModelB в вызове GET, тогда просто удалите ключ из pre_represented_data, как показано ниже.

class ModelASerializer(serializers.ModelSerializer):
    class Meta:
        model = ModelA
        fields = '__all__'

class ModelBSerializer(serializers.ModelSerializer):
    terminal = ModelASerializer(read_only=True)
    class Meta:
        model = ModelB
        fields = '__all__'
    
    def to_representation(self, instance):
        pre_represented_data = super().to_representation(instance)
        pre_represented_data['model_a'] = ModelASerializer(instance.model_a).data
        del pre_represented_data['id']  # deleting id of ModelB
        return pre_represented_data
Вернуться на верх