2015-09-28 8 views
6

私はDjango Rest Frameworkプロジェクトを扱っています。私のビューの一般的な応答は、アプリケーションクライアントが期待するものではありません。Django Rest Framework - シリアライザフィールドをデータベースのカラム名にマッピングする

アプリケーションクライアントは、関連するモデルのファイルがデータベースにあるように見えます。指定された例:model Cityには、country_id列で表されるCountryモデルへの外部キーがあります。

シリアライザのデフォルトフィールドをカスタムフィールドにマップするオプションはありますか?私はDjango Rest Frameworkのドキュメントをチェックしましたが、 "serializer_field_mapping"しか見つかりませんでしたが、それが自分の要求に合っているかどうかわかりませんし、使い方もわかりません。

何とか私はそれに近いアプローチを取っていますが、データを取得する場合のみ - 作成/更新すると、管理方法がわからないいくつかのエラーがスローされました。 :

ベロー私のmodels.pyファイルに実際の出力と出力が添付されています。可能であれば、国/地域に関連するデータが存在する場合はデータベース列FIELD_ID名。事前に

おかげで、

models.py

from django.db import models 
from django.contrib.postgres.fields import ArrayField 


class Country(models.Model): 

    name = models.CharField(max_length=150, unique=True, blank=False) 

    class Meta: 
     db_table = 'countries' 


class Region(models.Model): 

    name = models.CharField(max_length=150, unique=True, blank=False) 
    code = models.CharField(max_length=150, blank=True) 

    class Meta: 
     db_table = 'regions' 


class City(models.Model): 

    country = models.ForeignKey(Country) 
    region = models.ForeignKey(Region, null=True, blank=True, default=None) 
    name = models.CharField(max_length=150, unique=True, blank=False) 
    postal_codes = ArrayField(models.CharField(max_length=12, blank=True), null=True, blank=True, default=None) 

    def __str__(self): 
     if not self.region: 
      return '%s (%s)' % (self.name, self.country.name) 
     return '%s, %s (%s)' % (self.name, self.region.name, self.country.name) 

    class Meta: 
     db_table = 'cities' 

実際の王TPUT:

[ 
    { 
    "id": 1, 
    "name": "San Francisco", 
    "postal_codes": null, 
    "country": 1, 
    "region": 1 
    }, 
    { 
    "id": 2, 
    "name": "Palo Alto", 
    "postal_codes": null, 
    "country": 1, 
    "region": 1 
    }, 
    { 
    "id": 3, 
    "name": "New York City", 
    "postal_codes": null, 
    "country": 1, 
    "region": 2 
    }, 
    { 
    "id": 4, 
    "name": "London", 
    "postal_codes": null, 
    "country": 2, 
    "region": null 
    } 
] 

所望の出力:

[ 
    { 
    "id": 1, 
    "country_id": 1, 
    "region_id": 1, 
    "name": "San Francisco", 
    "postal_codes": null 
    }, 
    { 
    "id": 2, 
    "country_id": 1, 
    "region_id": 1, 
    "name": "Palo Alto", 
    "postal_codes": null 
    }, 
    { 
    "id": 3, 
    "country_id": 1, 
    "region_id": 2, 
    "name": "New York City", 
    "postal_codes": null 
    }, 
    { 
    "id": 4, 
    "country_id": 2, 
    "region_id": null, 
    "name": "London", 
    "postal_codes": null 
    } 
] 

答えて

2

ありがとうございます。ついにできた。以下のコードを参照してください。私は答えのコメントに大量の行を追加するオプションがないため、私の質問に答えます。

serializers.py

from rest_framework import serializers 
from .models import Country, Region, City 


class CountrySerializer(serializers.ModelSerializer): 

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


class RegionSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Region 
     fields = ('id', 'name', 'code') 


class CitySerializer(serializers.ModelSerializer): 

    country_id = serializers.PrimaryKeyRelatedField(
     queryset=Country.objects.all(), 
     required=True, 
     source='country', 
    ) 
    region_id = serializers.PrimaryKeyRelatedField(
     queryset=Region.objects.all(), 
     allow_null=True, 
     required=False, 
     source='region', 
    ) 

    country = CountrySerializer(
     read_only=False, 
     required=False, 
    ) 
    region = RegionSerializer(
     required=False, 
     allow_null=True, 
     read_only=True, 
    ) 

    class Meta: 
     model = City 
     fields = (
      'id', 
      'country', 'region', 
      'name', 'postal_codes', 
      'country_id', 'region_id', 
     ) 
5

あなたはこれを達成するために、あなたのシリアライザ上のフィールドのsourceパラメータを使用することができます。たとえば、次のように

from rest_framework import serializers 

from .models import City 


class CitySerializer(serializers.ModelSerializer): 
    country_id = serializers.IntegerField(source='country') 
    region_id = serializers.IntegerField(source='region') 

    class Meta: 
     model = City 
     fields = ('id', 'country_id', 'region_id', 'name', 'postal_codes') 

EDIT:ヤロスラフが指摘したように、この方法でそれをやったとき、あなたはsourceを含める必要はありません。ただし、fieldsのリストにcountry_idまたはregion_idを単に入れるだけでは不十分です。シリアライザでフィールドを指定する必要があります(country_id = serializers.IntegerField()など)。これをfieldsに含める必要があります。

+0

彼が 'country_id'と' region_id'内のIDを持って望んでいるので、OPは、 'source'を必要としていないようです。 –

+0

確かに、それはいくつかのジャンゴレストフレームワークのデフォルトの検証を提供しません。 'cities/city/{name:SanJosé、country_id:999999}'は、都市 "テーブル"のIntegrityErrorが/ cities/insertまたはupdateでHTMLに提供されます。 "cities_country_id_2cc874aa51973821_fk_countries_id"詳細:Key(country_id)=( 999)はテーブル "countries"には存在しません。また、データベーステーブルの制約についても同様です。 – jordimarinvalle

+0

@JordiMarínValle['PrimaryKeyRelatedField'](http://www.django-rest-framework。org/api-guide/relations /#primarykeyrelatedfield)を使用してください。 –

関連する問題