DjangoRestFrameworkで中間テーブルをネストした形のJsonで返す

##なぜ書いたのか
Django歴が長くはなく、ましてやDRFは初めてで、うまく活用できず悩んだので書いていく。
日本語の記事も少ないと感じたので、少しでも参考になればいいと思う。

Django, djangorestframeworkの説明は省きます。

重要な部分はserializerです。

##開発環境
macOS Mojave
python 3.6.7
Django 2.1.3
djangorestframework 3.9.0 

##Model

まずはDjangoのDocsにも書かれているmodelを例にとってモデルを定義していく

[Models | Django documentation | Django](https://docs.djangoproject.com/en/2.1/topics/db/models/)

```models.py

class Person(models.Model):
    name = models.CharField(max_length=128)
　　　　　　　　play = models.CharField(max_length=128)

    def __str__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)
```

##Viewsets

最終的にはそのGroupのMenmberとMenbmerのname,invite_resonを表示したいと考える
viewsetsもここでは重要ではないので最小限に抑える

```group_viewsets.py
class GroupViewsets(viewsets.ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
```

##Serialezer

- 第一段階
MemberのIDがネストされた形のjsonで表示

```serializer.py
class GroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = Group
        fields = (
            'name',
            'members',
        )
```

```json
{
  "name": "The Beatles",
  "members": [
    1,
    2,
    ...
  ]
}
```

memberに対してnameとplayも紐付いていて欲しいところ


- 第二段階

membersに対してPersonの詳細もネストされた状態で紐付いている

```serializer.py

class PersonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Person
        fields = (
            'name',
            'play',
        )

class GroupSerializer(serializers.ModelSerializer):
    members = PersonSerializer(many=True)

    class Meta:
        model = Group
        fields = (
            'name',
            'members',
        )
```

```json
{
  "name": "The Beatles",
  "members": [
    { 
      "name": "Ringo Starr",
      "play": "Drums"
    },
    { 
      "name": "Paul McCartney",
      "play": "Bass"
    },
    ...
  ]
}
```

Person情報が紐づいたはいいものの、invite_reasonも紐づいて欲しい

- 第三形態(最終)

membersにinvite_reasonが紐づいたjsonが欲しい


```serializers.py
class MembershipSerializer(serializers.ModelSerializer):
    name = serializers.ReadOnlyField(source="person.name")
    play = serializers.ReadOnlyField(source="person.play")

    class Meta:
        model = Membership
        fields = (
            'name',
            'play',
            'invite_reason',
        )

class GroupSerializer(serializers.ModelSerializer):
    members = MembershipSerializer(source='membership_set', many=True)

    class Meta:
        model = Group
        fields = (
            'name',
            'members',
        )
```

最初はMemberhipSerializerからpersonにアクセスしてnameをとるという発想ができなかった、僕はここでつまづきました.djangoの特性などがわかっていればすぐにできそうですが、、、

MembershipSerializerのperson=Personserializer()などやって、全然できずに悩んでいました.


```json
{
  "name": "The Beatles",
  "members": [
    { 
      "name": "Ringo Starr",
      "play": "Drums",
      "invite_reason": "Needed a new drummer."
    },
    { 
      "name": "Paul McCartney",
      "play": "Bass"
      "invite_reason": "Wanted to form a band."
    },
    ...
  ]
}
```

これで思い通りの結果を取得できるようになりました。

##今回学んだポイント

serializersのReadOnlyFieldやCharFieldで定義されていた関数、自分で定義した関数を呼び出すことが可能