1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Django REST Framework】Serializerの使い分け 初心者🔰

Posted at

はじめに

バックエンド開発をしているとフロントエンドができるだけ処理しやすい形データを渡してあげたいなぁと思いますよね?(フロントエンドの開発したことないんですが。。。)
初学者だけど!

シリアライザの使いわけ方がわからなかった
        +
親子関係を持つモデルを返却する際に階層を揃える方法
の2点を備忘録として残しておきます。

モデルのイメージ

以下のモデルがあったとします。
ER図親子.png

データの取得

大前提としてDjangoでは子テーブルから親テーブル参照することができます。

今回であれば以下のように、子から親を参照しに行くことができるんですね。

data = テーブルA.objects.select_related("テーブルB", "テーブルC").all()

-本題- データ返却(Serializerの準備)

Serialzerを準備していきます。

・問題点

以下のようなシリアライザにすると次の様な形式で出力されてしまう。

class TableBSerializer(serializers.ModelSerializer):
    """テーブルB(親)のシリアライザ"""
    class Meta:
        model = TableB
        fields = ["id", "value_b"]


class TableCSerializer(serializers.ModelSerializer):
    """テーブルC(親)のシリアライザ"""
    class Meta:
        model = TableC
        fields = ["id", "value_c"]


class TableASerializer(serializers.ModelSerializer):
    """テーブルA(子)のシリアライザ"""
    tableB = TableBSerializer() # テーブルBのシリアライザをネスト
    tableC = TableCSerializer() # テーブルCのシリアライザをネスト

    class Meta:
        model = TableA
        fields = ["id", "vlaue_a", "tableB", "tableC"]

レスポンスは以下の通り

{
  # テーブルAのキーをマッピングできていない
  "id": 0,
  "vlaue_a": "string",
  
  "tableB": {
    "id": 0,
    "value_b": "value_b"
  },
  "tableC": {
    "id": 0,
    "value_c": "value_c"
  }
}

理想はtable_aをキーとしてマッピングすることである。

{
  "tableA": {
    "id": 0,
    "value_a": "value_a"
  },
  "tableB": {
  #~~~~~~~省略~~~~~~~~~~~
}

・ModelSerailzerは単一のモデルを扱うもの

ModelSerializerはモデルをネストもできるが基本的には単一モデルの操作向き

変更点:
ModelSerializerで内包するのではなく、Serializerで内包することにした

class TableASerializer(serializers.ModelSerializer):
    """テーブルA(子)のシリアライザ"""
    class Meta:
        model = TableA
        fields = ["id", "vlaue_a"]


class TableBSerializer(serializers.ModelSerializer):
    """テーブルB(親)のシリアライザ"""
    class Meta:
        model = TableB
        fields = ["id", "value_b"]


class TableCSerializer(serializers.ModelSerializer):
    """テーブルC(親)のシリアライザ"""
    class Meta:
        model = TableC
        fields = ["id", "value_c"]


# serializers.Serializerに変更
class AllDataSerializer(serializers.Serializer):
    """新規追加: 返却用シリアライザ"""
    tableA = TableASerializer()
    tableB = TableBSerializer()
    tableC = TableCSerializer() 
{
  "tableA": {
    "id": 0,
    "value_a": "value_a"
  },
  "tableB": {
    "id": 0,
    "value_b": "value_b"
  },
  "tableC": {
    "id": 0,
    "value_c": "value_c"
  }
}

フラットになりました

おまけ

取得したデータはtableAを起点として取得したものである。
上記の修正を行ってもでエラーが発生する場合は、以下の追記をすることで解消することが可能である。

class AllDataSerializer(serializers.Serializer):
    """返却用シリアライザ"""
    tableA = TableASerializer(source="*")
    tableB = TableBSerializer()
    tableC = TableCSerializer() 

source="*"は自身のインスタンスを全て渡すオプションである。これによりソースを参照することができるようになる。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?