0

I have a model:

class Schedule(LogSaveDeleteMixin, models.Model):
    name = models.CharField(max_length=40)
    start_date = models.DateTimeField(null=True, blank=True)

class DeliveryChannel(LogSaveDeleteMixin, models.Model):
    name = models.CharField(unique=True, max_length=40)
    state = models.CharField(choices=DeliveryChannelState.choices, default='draft', max_length=15)
    schedule = models.ForeignKey(Schedule, null=True, on_delete=models.SET_NULL)

And standard ModelSerializer:

class DeliveryChannelsSerializer(serializers.ModelSerializer):
    class Meta:
        model = DeliveryChannel
        fields = '__all__'

class ScheduleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Schedule
        fields = '__all__'

For read requests (GET) I want to receive schedule field as a nested serializer:

{
  "id": 0,
  "name": "string",
  "state": "archived",
  "schedule": {
    "id": 0,
    "name": "string",
    "start_date": "2022-08-12T02:41:32.187Z",
  }
}

But for writing (POST, PUT) I want to get only schedule id:

{
  "id": 0,
  "name": "string",
  "state": "archived",
  "schedule": 0
}

I would like to know the best practices for do this

privod
  • 209
  • 5
  • 7

2 Answers2

1

You can just set some fields in the DeliveryChannelsSerializer.

class DeliveryChannelsSerializer(serializers.ModelSerializer):
    schedule = ScheduleSerializer(read_only = True)
    schedule_id = serializers.IntegerField(write_only = True)

    class Meta:
        model = DeliveryChannel
        fields = '__all__'
        extra_fields = ['schedule_id']

The POST payload should be like the following:

{
  "name": "string",
  "state": "archived",
  "schedule_id": 1
}
Metalgear
  • 3,391
  • 1
  • 7
  • 16
1

You can make two different serializers for DeliveryChannels.

class ScheduleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Schedule
        fields = ['id', 'name', 'start_date']


class DeliveryChannelSerializer(serializers.ModelSerializer):
    # Serializer for POST,PUT
    class Meta:
        model = DeliveryChannel
        fields = ['id', 'name', 'state', 'schedule']


class DeliveryChannelDetailSerializer(serializers.ModelSerializer):
    # Serializer for GET
    
    schedule = ScheduleSerializer()

    class Meta:
        model = DeliveryChannel
        fields = ['id', 'name', 'state', 'schedule']

if you use ModelViewSet you need to override get_serializer_clas

def get_serializer_class(self):
    if self.action == "list":
        return DeliveryChannelDetailSerializer
    return DeliveryChannelSerializer
Ryan
  • 77
  • 1
  • 7