3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-05-03

DRF-Writable-Nested を使う

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

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

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

使い方

requirements.txtにdrf-writable-nestedを追加

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

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

Tips

例1: 親、子、孫、(ひ孫...)モデルを同時に登録したい

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モデルのレコードをまとめて作成できる。

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モデルのレコードをまとめて作成できる。

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

user_serializer = UserSerializer(data=data)
user_serializer.is_valid(raise_exception=True)
user = user_serializer.save()
3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?