@JonGalt

Как передать объект POST запросом в Serializer relations DRF?

На клиенте Vue на сервере Django Rest FrameWork.

# models.py
class UnitMeasure(models.Model):
    name = models.CharField(max_length=128, verbose_name='Ед. изм.')
    is_archive = models.BooleanField(verbose_name='В архиве', default=False)

class Material(models.Model):
    name = models.CharField(max_length=200, verbose_name=u'Название материала')
    unit_measure = models.ForeignKey(UnitMeasure, null=True, blank=True, verbose_name='Ед. изм.')

#serializers.py

class UnitMeasureSerializer(serializers.ModelSerializer):
    class Meta:
        model = UnitMeasure
        fields = ('__all__')


class MaterialSerializer(serializers.ModelSerializer):
    unit_measure = UnitMeasureSerializer()

    class Meta:
        model = Material
        fields = ('id', 'name', 'unit_measure')
    
def create(self, validated_data):
        un_m = validated_data.pop('unit_measure')
        material = Material.objects.create(**validated_data, unit_measure_id=un_m.id)
        return material


На клиенте при создании какого-либо объекта удобно передавать в качестве первичного ключа связанной модели не id а целый объект. В моем случае при создании материала мне надо в качестве ед. изм. передать не просто id, а
{
    "name": "Бетон В30",
    "unit_measure": {
      "id": 1,
      "name": "м3"
    }
}

При такой организации serializers.py DRF почему-то при валидации обрезает id из словаря unit_measure и оставляет только name и я не могу добавить ед. изм. при создании материала.
Подскажите как быть?
  • Вопрос задан
  • 375 просмотров
Пригласить эксперта
Ответы на вопрос 1
Можно попробовать сделать так:
1) Указать метод __str__ у UnitMeasure
def __str__(self):
    return self.name

2) создать кастомный field
class CustomPrimaryKeyRelatedField(PrimaryKeyRelatedField):
    def to_representation(self, value):
        return {'id': value.pk, 'name': str(value)}
    
    def to_internal_value(self, data):
        if isinstance(data, dict):
            data = data.get('id')
        return super(CustomPrimaryKeyRelatedField, self).to_internal_value(data)

3) указать этот field в сериализаторе
class MaterialSerializer(serializers.ModelSerializer):
    unit_measure = CustomPrimaryKeyRelatedField()

    class Meta:
        model = Material
        fields = ('id', 'name', 'unit_measure')

Работоспособность не проверял
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы