DRF在REST API上的两个单独的读写字段中公开模型字段

时间:2015-09-04 19:12:32

标签: python django rest django-rest-framework

我使用的是Python 2.7,DRF 3.1.3,Django 1.4.21(我知道它已经很久了,但它是一个很大的代码库,有一天我们会迁移)。现实世界的商业案例比这更复杂,这是简化版本。

我有一个模特:

class Person(models.Model):
    foo = models.CharField(max_length=2, blank=True, null=True)

在REST API上我想公开两个字段,它们都来自foo。这两个字段都应该是可写的,当我写入时,这两个字段都会以某种方式设置foo字段。 尝试1:棒是不幸的只读

class PersonSerializer(serializers.ModelSerializer):
    bar = serializers.SerializerMethodField()

    class Meta:
        model = Person
        fields = ('id', 'foo', 'bar')

    def get_bar(self, obj):
        return get_bar(obj.foo) # not relevant now what get_bar does

尝试2:试图以某种方式伪造一个字段

class PlaceholderCharField(serializers.CharField):
    def to_representation(self, obj):
        pass

    def to_internal_value(self, data):
        pass

class PersonSerializer(serializers.ModelSerializer):
    bar = PlaceholderCharField()

    class Meta:
        model = Person
        fields = ('id', 'foo', 'bar')

    def to_representation(self, instance):
        data = super(PersonSerializer, self).to_representation(instance)
        data['bar'] = get_bar(instance.foo)
        return data

    def to_internal_value(self, data):
        instance = super(PersonSerializer, self).to_internal_value(data)
        if data.has_key('bar') and not data.has_key('foo'):
            instance.foo = get_foo(data['bar']) if data['bar'] else None
        return instance

后者显然错误地抱怨Person模型没有条形字段。这是真的。如何解决这个问题呢?我可以在序列化程序to_representationto_internal_value中设置/获取foo和bar。我只想在DRF中指定一个字段,该字段仅存在于REST API侧,并且在模型端没有关联的字段。我可以照顾变换。那个字段应该是读写的,否则我可以用SerializerMethodField来解决它。

2 个答案:

答案 0 :(得分:2)

我不确定你的用例,看起来有点奇怪,但为什么不在你的模型上添加一个属性。例如,

   @property
    def bar(self):
        """
        Used for DRF only.
        """
        return None # or self.foo

然后将其添加到序列化程序中的字段中(无需使用PlaceholderCharField

fields = ('id', 'foo', 'bar') 

其余的将会有效。

答案 1 :(得分:2)

稍微调整你的第一次尝试,你可以为该字段添加别名,没问题:

class PersonSerializer(serializers.ModelSerializer):
    #                 vvvvvvvvv
    bar = serializers.CharField(
       source='foo', required=False
    )# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    class Meta:
        model = Person
        fields = ('id', 'foo', 'bar')

我仍然使用DRF 2.4.4来获得更好的嵌套,多对象嵌套序列化程序支持,但是我使用该方法来对URL及其关联对象进行别名处理,以处理Angular JS比较的方式一些控件中的对象。 e.g。

class SensorSerializer(serializers.HyperlinkedModelSerializer):
    location_obj = SensorLocationSerializer(source='location',read_only=True,required=False)
    class Meta:
        model = Sensor
        fields = ('url', 'id', 'name', 'serial_number', 'location', 
            'location_obj', 'active')