Django REST Framework  関連性のあるモデルを同時に登録したい

## DRF-Writable-Nested を使う

https://github.com/beda-software/drf-writable-nested

登録するモデルのカラムが別のモデルを順参照、あるいは逆参照している場合は、その参照先モデルの内容をネストしてjsonリクエストを作成する。そのようなリクエストを受けて、上記ライブラリは関連するモデルを含めてレコードを一括で作成してくれる。

jsonがネストしている例: OrderモデルがOrderDetailモデルを順参照している場合

```javascript:order.json
{
    'customer_name': 'hogehoge',
    'order_detail': {
        'name': 'curry_rice'  // order_detailの内容がネストしている
    }
}
```

### 使い方
requirements.txtにdrf-writable-nestedを追加

別モデルを順参照（逆参照）しているモデルに対してWritableNestedSerializerを継承してシリアライザーを作成する。

順参照→子モデルが親モデルを参照すること
逆参照→親モデルが子モデルを参照すること

## Tips
#### 例1: 親、子、孫、（ひ孫...）モデルを同時に登録したい
```python:models.py
from django.db import models

# 親モデル
class OrganizationStructure(models.Model):
    name = models.CharField(max_length=100)

# 子モデル
class Organization(models.Model):
    organization_structure = models.ForeignKey(OrganizationStrucure, on_delete=models.CASCADE)

# 孫モデル
class CorporateInformation(models.Model):
    company_name = models.CharField(max_length=100)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
```
作成するモデルの主がCorporateInformationであり、孫は子を、子は親を順参照していると捉えるケース。孫、子モデルそれぞれのシリアライザーに対してWritableNestedModelSerializerを継承して作成する。

```serializers.py
from rest_framework import serializers
from drf_writable_nested.serializers import WritableNestedModelSerializer

class CorporateInformationSerializer(WritableNestedModelSerializer):
    organization = OrganizationSerializer()

    class Meta:
        model = CorporateInformation
        fields = ('id', 'organization', 'name')
 
 class OrganizationSerializer(WritableNestedModelSerializer):
    organization_structure = OrganizationStructureSerializer()

    class Meta:
        model = Organization
        fields = ('id', 'organization_structure',)
 
class OrganizationStrucureSerializer(serializers.ModelSerializer):

    class Meta:
        model = OrganizationStructure
        fields = ('id', 'value')
```
結果、以下のようなjsonを受け取ることでCorporateInformation, Organization, OrganizationStructureモデルのレコードをまとめて作成できる。

```python
data = {
    'company_name': 'hoge株式会社',
    'organization': {
        'organization_structure': {
            'name': '個人'
        }
    }
}
corporate_information_serializer = CorporateInformationSerializer(data=data)
corporate_information_serializer.is_valid(raise_exception=True)
corporate_information = corporate_information_serializer.save()
```

#### 例2: 親を起点にモデルを作成するパターン
```models.py
from django.db import models

# 親1モデル
class User(models.Model):
    username = models.CharField(max_length=100)

# 子モデル
class Profile(models.Model):
    user = models.ForeignKey(User, related_name='profile', on_delete=models.CASCADE)
    access_key = models.ForeignKey(AccessKey, null=True, on_delete=models.CASCADE)

# 親2モデル
class AccessKey(models.Model):
    key = models.CharField(max_length=100)
```
作成するモデルの主がUserであり、親1が子を逆参照し、その子が別の親2を順参照していると捉えるケース。親1、子モデルのシリアライザーをWritableNestedModelSerializerを継承して作成する。

```serializers.py
from rest_framework import serializers
from drf_writable_nested.serializers import WritableNestedModelSerializer

class UserSerializer(WritableNestedModelSerializer):
    profile = ProfileSerializer()

    class Meta:
        model = User
        fields = ('pk', 'profile', 'username',)
 
 class ProfileSerializer(WritableNestedModelSerializer):
    access_key = AccessKeySerializer(allow_null=True)

    class Meta:
        model = Profile
        fields = ('pk', 'access_key',)
 
class AccessKeySerializer(serializers.ModelSerializer):

    class Meta:
        model = AccessKey
        fields = ('pk', 'key',)
```
結果、以下のようなjsonを受け取ることでUser, Profile, AccessKeyモデルのレコードをまとめて作成できる。

```python
data = {
    'username': 'test',
    'profile': {
        'access_key': {
            'key': 'key',
        },
    },
}

user_serializer = UserSerializer(data=data)
user_serializer.is_valid(raise_exception=True)
user = user_serializer.save()
```