使用相同的字段名称来序列化和反序列化Django REST Framework中的不同字段

时间:2015-10-18 00:12:13

标签: django django-rest-framework

我们说我有以下型号......

class Product(models.Model):
    name = models.CharField()

class Gift(models.Model):
    product = models.ForeignKey(Product)
    message = models.CharField()

......以下序列化程序......

class GiftSerializer(serializers.ModelSerializer):
    product = ProductSerializer(read_only=True)

    class Meta:
        model = Gift
        fields = ('product', 'message', )

...以及与' / gifts /'。

相关联的以下基于类的视图
from rest_framework.generics import CreateListAPIView 

class GiftList(CreateListAPIView):
    queryset = Gift.objects.all()
    serializer_class = GiftSerializer

如何使用关键产品'来创造礼物?代表这样的外键主键

self.client.post('/gifts/', {'product': 1, 'message': 'bar'})

但同时使用关键产品'

返回包含嵌套产品详情的信息
self.client.get('/gifts/')
# {0: {"product": {"name": "foo"}, "message": "bar"}}

我通过将另一个只写的IntegerField添加到名为GiftSerializer的{​​{1}}并覆盖product_pk来实现我想要的目标:

to_internal_values

但问题是,如果验证失败,则使用字段def to_internal_value(self, data): data['product_pk'] = data.pop('product')[0] return super().to_internal_value(data) 而不是product_pk返回异常,这是我希望的。

product

谢谢!

2 个答案:

答案 0 :(得分:2)

另一种方法是创建两个序列化程序,

class GiftReadSerializer(serializers.ModelSerializer):
    product = ProductSerializer(read_only=True)

    class Meta:
        model = Gift
        fields = ('product', 'message', )

class GiftWriteSerializer(serializers.ModelSerializer):    
    class Meta:
        model = Gift
        fields = ('product', 'message', )

然后在基于类的视图中,您可以利用get_serializer_class钩子:

from rest_framework.generics import CreateListAPIView 

class GiftList(CreateListAPIView):
    queryset = Gift.objects.all()
    serializer_class = GiftSerializer

    def get_serializer_class(self):
        if self.request.method == ('POST' or 'PUT' or 'PATCH'):
            return GiftWriteSerializer
        else:
            return GiftReadSerializer

答案 1 :(得分:0)

我设法通过覆盖to_internal_value并动态修改字段来完成这项工作。

product_field = ProductSerializer()
pk_product_field = serializers.PrimaryKeyRelatedField(
     queryset=Product.objects.all())

class GiftSerializer(object):
    product = product_field

    class Meta:
        model = Gift
        fields = ('product', 'message', )

    def to_internal_value(self, data):
        self.fields['product'] = pk_product_field
        internal_value = super().to_internal_value(data)
        self.fields['product'] = product_field
        return internal_value