何が出来るようになるか
Djangoで一対多のリレーションをJSONで返却するAPIを作成した場合、以下の様なレスポンスが返ってくると思います。この時、外部キーで参照される値のキー名employee_set
を別名(employees
)に変更する方法を紹介します。
レスポンス(キー名変更前)
キー名 employee_set
を employees
にしたい。
[
{
"id": "157b2b72-8315-446d-8120-07b408871ef3",
"name": "ABC",
"employee_set": [ # キー名を変更したい
{
"name": "やまだ"
},
{
"name": "すずき"
}
]
},
{
"id": "5ce3f3fe-7d3c-41c3-b3c0-f11d7d26d59f",
"name": "XYZ",
"employee_set": [ # キー名を変更したい
{
"name": "たなか"
},
{
"name": "たなべ"
}
]
}
]
環境
- Python: Python 3.7.1
- Django: 2.2.5
- djangorestframework: 3.10.3
Model
- 会社(1):従業員(多)の簡単なモデルを作成します
from django.db import models
import uuid
class Company(models.Model):
"""会社テーブル"""
class Meta:
db_table = 'company'
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(verbose_name="会社名", max_length=30)
def __str__(self):
return self.name
class Employee(models.Model):
"""従業員テーブル"""
class Meta:
db_table = 'employee'
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(verbose_name="氏名", max_length=30)
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=False)
def __str__(self):
return self.name
Serializer
- Djangoでは以下のルールがあります
- ForeignKeyを設定したモデルには、関連先のモデルの主キーを扱うために
「ForeignKey のフィールド名」_id
が付与される- 今回の場合は、EmployeeモデルからCompanyモデルを参照する
- ForeignKeyを設定したモデルには、関連先のモデルを参照するために`「ForeignKey のフィールド名」で参照できる
- ForeignKeyが設定されていないモデルでは、逆参照をするために「逆参照先のモデルクラス名(小文字)_set`で逆参照できる
- 今回の場合は、CompanyモデルからEmployeeモデルを参照する
- ForeignKeyを設定したモデルには、関連先のモデルの主キーを扱うために
上記のルールに従って、CompanyのオブジェクトにEmployeeのオブジェクトを入れ子にして返却する場合は、以下の実装になります。その場合、CompanySerializer
クラスに上記のルール「3」に従って、employee_set
という変数名を利用して、fields
の配列に設定する必要があります。
from rest_framework import serializers
from .models import Company, Employee
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = ['name']
class CompanySerializer(serializers.ModelSerializer):
employee_set = EmployeeSerializer(many=True)
class Meta:
model = Company
fields = ['id', 'name', 'employee_set']
View
ModelViewSet
を継承するだけでサクッとCRUDが作成できるのは本当に助かります;;
from rest_framework import viewsets
from .models import Company, Employee
from .serializers import CompanySerializer, EmployeeSerializer
class CompanyViewSet(viewsets.ModelViewSet):
queryset = Company.objects.all()
serializer_class = CompanySerializer
class EmployeeViewSet(viewsets.ModelViewSet):
queryset = Employee.objects.all()
serializer_class = EmployeeSerializer
変更方法
2つ方法があります。
-
serialziers.py
を変更する方法 -
models.py
を変更する方法(本記事を記載中、周辺調査の際に見つけました)-
serializers.py
も変更が必要
-
serialziers.py
を変更して適用する方法
from rest_framework import serializers
from .models import Company, Employee
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = ['name']
class CompanySerializer(serializers.ModelSerializer):
# employee_set = EmployeeSerializer(many=True)
employees = EmployeeSerializer(many=True, source='employee_set')
class Meta:
model = Company
fields = ['id', 'name', 'employees']
models.py
を変更して適用する方法
外部キーを作成するForeignKey
にrelated_name="キー名"
を指定します。
from django.db import models
import uuid
class Company(models.Model):
"""会社テーブル"""
class Meta:
db_table = 'company'
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(verbose_name="会社名", max_length=30)
def __str__(self):
return self.name
class Employee(models.Model):
"""従業員テーブル"""
class Meta:
db_table = 'employee'
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(verbose_name="氏名", max_length=30)
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=False, related_name="employees") # related_nameを指定する
def __str__(self):
return self.name
from rest_framework import serializers
from .models import Company, Employee
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = ['name']
class CompanySerializer(serializers.ModelSerializer):
employees = EmployeeSerializer(many=True)
class Meta:
model = Company
fields = ['id', 'name', 'employees']
レスポンス(変更後)
キー名がemployee_set
からemployees
に変更されていることが確認できます。
[
{
"id": "157b2b72-8315-446d-8120-07b408871ef3",
"name": "ABC",
"employees": [
{
"name": "やまだ"
},
{
"name": "すずき"
}
]
},
{
"id": "5ce3f3fe-7d3c-41c3-b3c0-f11d7d26d59f",
"name": "XYZ",
"employees": [
{
"name": "たなか"
},
{
"name": "たなべ"
}
]
}
]
最後に
DjangoのRestFrameworkを使って返却されるJSONのキー名を変更する方法を紹介しました。Web系のフレームワーク作るならRailsの方が日本語の情報があったり、特に工夫せずにパフォーマンスを上げるならGoなどの選択肢があると思いますが、私の所属している業界では何かと周辺ツールがPythonのライブラリを提供してることが多く、趣味でも活かせそうなのでDjangoを選定しました。少しでも皆さんのお役に立てると幸いです。