DRF-Writable-Nested を使う
登録するモデルのカラムが別のモデルを順参照、あるいは逆参照している場合は、その参照先モデルの内容をネストしてjsonリクエストを作成する。そのようなリクエストを受けて、上記ライブラリは関連するモデルを含めてレコードを一括で作成してくれる。
jsonがネストしている例: OrderモデルがOrderDetailモデルを順参照している場合
{
'customer_name': 'hogehoge',
'order_detail': {
'name': 'curry_rice' // order_detailの内容がネストしている
}
}
使い方
requirements.txtにdrf-writable-nestedを追加
別モデルを順参照(逆参照)しているモデルに対してWritableNestedSerializerを継承してシリアライザーを作成する。
順参照→子モデルが親モデルを参照すること
逆参照→親モデルが子モデルを参照すること
Tips
例1: 親、子、孫、(ひ孫...)モデルを同時に登録したい
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を継承して作成する。
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モデルのレコードをまとめて作成できる。
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: 親を起点にモデルを作成するパターン
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を継承して作成する。
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モデルのレコードをまとめて作成できる。
data = {
'username': 'test',
'profile': {
'access_key': {
'key': 'key',
},
},
}
user_serializer = UserSerializer(data=data)
user_serializer.is_valid(raise_exception=True)
user = user_serializer.save()