如何使Serializer中的字段可读可写

时间:2019-05-15 20:18:31

标签: python django django-rest-framework django-serializer

我正在为我的模型编写一个序列化器,可以使用GET,POST和PATCH端点进行访问。我的模型中有一个属性,我将其用作字段的源。但是,在序列化程序字段中使用source=使其仅准备就绪。

如果我从

删除source="get_field1"

field1 = serializers.NullBooleanField(source="get_field1")

然后我就可以更新数据。

但是我必须使用源来获取字段的正确值。

class MyModel(models.Model):
    field1 = NullBooleanField(default=None)

    @property
    get_field1(self):
       data = True
       # ...some logic
       return data

现在我有一个正在使用的序列化器

    class MyModelSerializer(serializers.ModelSerializer):
        field1 = serializers.NullBooleanField(source="get_field1")
        class Meta:
             model = MyModel
             fields = ('field1')

现在在我的API端点中,我这样做

    serializer = MyModelSerializer(my_model, data=request.data, partial=True)
    if serializer.is_valid():
        serializer.save() # <- throws error "can't set attribute"

此外,我还要提到序列化程序中的字段是由属性名称而不是字段名称引用的。

示例:如果我这样做

>> serializer.validated_data

>> 'OrderedDict(['get_field1'], True) # <- shouldn't this by field1 and not get_field1

2 个答案:

答案 0 :(得分:3)

这可以通过覆盖序列化程序的 __init__() 方法来完成。除此之外,我们还需要将一些 context 数据传递给序列化程序,以区分GETPOST和{ {1}}个请求。

PATCH

并且在序列化数据时,不要忘记将请求作为上下文传递,就像

class MyModelSerializer(serializers.ModelSerializer):
    field1 = serializers.NullBooleanField()  # remove "source" argument from here

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.context['request'].method == 'GET':
            self.fields['field1'] =serializers.NullBooleanField(source= "get_field1")

    class Meta:
        model = MyModel
        fields = ('field1',)

答案 1 :(得分:2)

@JPG的回答很好,但是我觉得这是一种怪诞的方式。

我将重写Serializer的to_representation方法以实现您的目的。

这就是你可以做的

class MyModelSerializer(serializers.ModelSerializer):
        field1 = serializers.NullBooleanField() # get rid of source

        def to_representation(self, instance):
             data = super(MyModel, self).to_representation(instance)
             data.update({
                  'field1': instance.get_field1
             })
             return data       

        class Meta:
             model = MyModel
             fields = ('field1')

这样,您将隐式提供源,并且您的字段可写。因此,每次执行GET,POST或PATCH时,您都会获得正确的值。