##なぜ書いたのか
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
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もここでは重要ではないので最小限に抑える
class GroupViewsets(viewsets.ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
##Serialezer
- 第一段階
MemberのIDがネストされた形のjsonで表示
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = (
'name',
'members',
)
{
"name": "The Beatles",
"members": [
1,
2,
...
]
}
memberに対してnameとplayも紐付いていて欲しいところ
- 第二段階
membersに対してPersonの詳細もネストされた状態で紐付いている
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',
)
{
"name": "The Beatles",
"members": [
{
"name": "Ringo Starr",
"play": "Drums"
},
{
"name": "Paul McCartney",
"play": "Bass"
},
...
]
}
Person情報が紐づいたはいいものの、invite_reasonも紐づいて欲しい
- 第三形態(最終)
membersにinvite_reasonが紐づいたjsonが欲しい
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()などやって、全然できずに悩んでいました.
{
"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で定義されていた関数、自分で定義した関数を呼び出すことが可能