使用to_internal_value()和to_representation()的Django Rest Framework读写平面序列化器

时间:2018-07-24 05:44:21

标签: django django-rest-framework

我已经在drf文档之后成功实现了writable-nested-serializer,并且还可以使用to_representation()方法更改其表示形式,以使其看起来更简洁。

\ initial数据结构,其中POST与修改的crete()一起正常工作

{
    "id": 1033,
    "client": {
        "client_name": "BAC"
    },
    "brand": {
        "brand_name": "SDA"
    },
    "order_date": "2018-01-25",
    "shipment_date": "2018-01-26"
}

在应用to_representation()和PATCH之后的\数据结构可以在修改后的update()很好的情况下工作,但不能进行POST,而PUT则不能。

    {
        "id": 1033,
        "order_date": "2018-01-25",
        "shipment_date": "2018-01-26",
        "client_name": "BAC",
        "brand_name": "SDA"
    }

但是,我似乎无法正确实现to_internal_value()方法,因此我可以使用新的表示形式编写可写嵌套的序列化器。以下是尽管自定义create()方法并使用所需数据进行POST仍收到的错误。

\ POST数据

{
    "order_date": "2017-10-26",
    "shipment_date": "2017-11-11",
    "client_name": "ABC",
    "brand_name": "DEF"
}

\错误信息

{
    "client": [
        "This field is required."
    ],
    "brand": [
        "This field is required."
    ]
}

下面是我的代码。使用PATCH时,update()方法可以正常工作。但是POST和PUT无法正常工作,因此我认为我缺少一些正确链接create()和to_internal_value()方法的代码。任何帮助将不胜感激。

/serializers.py

class OrderSerializer(serializers.ModelSerializer):
    client = ClientSerializer()
    brand = BrandSerializer()

    class Meta:
        model = Order
        fields = ('id', 'client', 'brand', 'order_date',
                  'shipment_date',)

    def to_representation(self, obj):
        representation = super().to_representation(obj)
        client_representation = representation.pop('client')
        brand_representation = representation.pop('brand')
        for key in client_representation:
            representation[key] = client_representation[key]
        for key in brand_representation:
            representation[key] = brand_representation[key]
        return representation

    def to_internal_value(self, data):
        client_internal = {}
        brand_internal = {}
        for key in ClientSerializer.Meta.fields:
            if key in data:
                client_internal[key] = data.pop(key)
        for key in BrandSerializer.Meta.fields:
            if key in data:
                brand_internal[key] = data.pop(key)
        internal = super(OrderSerializer, self).to_internal_value(data)
        internal['client'] = client_internal
        internal['brand'] = brand_internal

        return internal

    def create(self, validated_data):
        client_data = validated_data.pop('client')
        brand_data = validated_data.pop('brand')
        client, created = Client.objects.get_or_create(
            client_name=client_data['client_name'])
        brand, created = Brand.objects.get_or_create(
            brand_name=brand_data['brand_name'])
        order = Order.objects.create(
            client=client, brand=brand, **validated_data)
        return order

    def update(self, instance, validated_data):
        client_data = validated_data.pop('client')
        brand_data = validated_data.pop('brand')
        client, created = Client.objects.get_or_create(
            client_name=client_data['client_name'])
        brand, created = Brand.objects.get_or_create(
            brand_name=brand_data['brand_name'])
        instance.brand = brand
        instance.client = client
        instance.order_date = validated_data['order_date']
        instance.shipment_date = validated_data['shipment_date']
        instance.save()
        return instance

1 个答案:

答案 0 :(得分:0)

我尝试了您的代码,正如我在评论中所建议的那样,这应该对您有帮助:

class OrderSerializer(serializers.ModelSerializer):
    client = ClientSerializer(required=False)
    brand = BrandSerializer(required=False)

有了这个,我就能用您的json输入发送POST请求并创建订单。