Django REST Frameworkでフィールド名を変更する方法


93

SQLのエイリアスのようにDRFシリアライザのモデルフィールド名を変更しようとしています。別の方法を試しましたが、成功できません。

models.py

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

    def alias_alternate_name(self):
        return self.alternate_name

serializers.py

class ParkSerializer(serializers.ModelSerializer):

    location = serializers.Field(source='alias_alternate_name')
    #location = serializers.SerializerMethodField(source='alias_alternate_name')

    #alternate_name as location


    class Meta:
        model = Park
        fields = ('id', 'name', 'location')

また、Django Querysetにエイリアスを追加しようとしましたが、変更できません。

更新しました

これは私が直面している例外です

/ ViewName / 'module'オブジェクトのAttributeErrorに属性 'Field'がありません

これどうやってするの?


1
serializers.SerializerMethodFieldアプローチの正しい実装を使用していますか?:私はこの意味serializers.SerializerMethodField('get_location')def get_location(self, obj): ...
erthalion

の輸入を見ることができますserializers.pyか?
joerick 14

OPが下のより良い答えの代わりに部分的に間違った混乱する答えを受け入れたため、質問に反対票を投じます...
NeuronQ

回答:


56

使用できますserializers.SerializerMethodField

これがモデル Parkで、nameフィールドとalternate_nameフィールドがあります。

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

これがパークモデルのシリアライザ、ParkSerializerです。これにより、alternate_nameの名前が場所に変更されます。

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SerializerMethodField('get_alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

    def get_alternate_name(self, obj):
        return obj.alternate_name

また、あなたが使用することができますserializers.CharFieldsource属性:

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.CharField(source='other_fields')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

__外部キーをトラバースするDjangoの表記法も機能します。

location = serializers.CharField(source='OtherModel__other_fields')

APIの戻り値の型を変更する場合も同じ原則が適用されるためserializers.DecimalField(source=...)、他のフィールド型も変更できます。

ただし、これは読み取り専用フィールドでのみ機能します。


現在、この例外は/ ViewName /でAttributeErrorをスローしています 'module'オブジェクトには属性 'SerializerMethodField'がありません
Shoaib Ijaz

1
作成および編集リクエストでのこのワークアウトはどうでしょうか?
iankit 2015年

1
'Zen of Python'の13行目:「それを行うための明白な方法は1つ(できれば1つだけ)あるべきです。」
iankit

13
これは受け入れられる答えではありません。私がこれを書いている時点では、約5倍の賛成票がある以下の1つを参照してください。
cderwin 2016年

5
これは悪い解決策です。source以下で説明するように、代わりにkwargを使用してください。
Patrick

212

シリアライザーフィールドと、一般的に「ソース」と呼ばれるシリアライザーには、モデルフィールドからデータのソースを指定できる非常に優れた機能があります。

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SomeSerializerField(source='alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

ここで、serializers.SomeSerializerFieldは、モデルが示唆するようにserializers.CharFieldにすることができますが、他のフィールドによっても可能です。また、代わりにリレーショナルフィールドや他のシリアライザーを配置することもできますが、これも魅力のように機能します。つまり、alternate_nameが別のモデルの外部キーフィールドであったとしても。

class ParkSerializer(serializers.ModelSerializer):
    locations = AlternateNameSerializer(source='alternate_name', many=true)

    class Meta:
        model = Park
        fields = ('other_fields', 'locations')

class AlternateNameSerializer(serializers.ModelSerialzer):
    class Meta:
        model = SomeModel

これは、リクエストの作成、削除、変更タイプでも機能します。シリアライザのフィールド名とモデルのフィールド名の1対1のマッピングを効果的に作成します。


私は同意しました、それsourceはより一般的なアプローチです。しかし、質問でそれを使用するいくつかの試みを見ることができるので、そのように答えたい場合は、元のコードが機能していない理由も明らかにする必要がありますね。
エルタリオン2016年

あなたのコードは問題なく動作します。リクエストがリストとリトリーブである
限り

どちらの回答も不完全です。外部キーの場合、このメソッドは、新しいParkを作成するときに、親オブジェクト全体(alternate_name)をPOSTリクエストのdictとして指定する必要があることを意味します。これは、親オブジェクトがすでに存在するため、異常です。IDを介して外部インスタンスに言及できるはずです。
stelios 2016年

私の場合(外部キー)でこの問題を解決しましたlocations = serializers.PrimaryKeyRelatedField(source='alternate_name', queryset=AlternateName.objects.all())。どうやらRelatedField同様に使用することができます。
stelios 2016年

@chefarov source = 'new_name'は、シリアライザフィールド、関係、その他の関連するシリアライザなどに与えることができる一般的な引数です。答えが不完全であると言う理由がわかりません。
iankit 2016年

14

これは書き込み操作でも機能します

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.CharField(source='alternate_name')

    class Meta:
        model = Park
        fields = ('id', 'name', 'location')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.