J
J
JonGalt2018-04-22 15:50:59
Vue.js
JonGalt, 2018-04-22 15:50:59

How to pass a POST object as a request to Serializer relations DRF?

On a Vue client on a Django Rest FrameWork server.

# 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

On the client, when creating an object, it is convenient to pass not id, but the whole object as the primary key of the associated model. In my case, when creating a material, I need as a unit. rev. pass not just id, but
{
    "name": "Бетон В30",
    "unit_measure": {
      "id": 1,
      "name": "м3"
    }
}

With such an organization, serializers.py DRF for some reason, during validation, cuts off the id from the unit_measure dictionary and leaves only the name and I can’t add a unit. rev. when creating material.
Tell me how to be?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
P
Pavel Aksenov, 2018-04-23
@hellmin

You can try to do this:
1) Specify the __str__ method for UnitMeasure

def __str__(self):
    return self.name

2) create a custom 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) specify this field in the serializer
class MaterialSerializer(serializers.ModelSerializer):
    unit_measure = CustomPrimaryKeyRelatedField()

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

Functionality not tested

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question