【RestFramework】関連するモデル一覧を出力する


関連するモデルを出力することを学んだのでメモする

前提

各、都道府県と市区町村が関連するmodelを用意

  1. Prefは都道府県
  2. Cityは市区町村を指す
class Pref(models.Model):
    pref_name = models.CharField(max_length=255, blank=True)
    pref_code = models.CharField(max_length=255, blank=True)

    def __str__(self):
        return self.pref_name


class City( models.Model ):
    city_name = models.CharField( max_length=255, blank=True )
    city_code = models.CharField( max_length=255, blank=True )
    pref = models.ForeignKey(Pref, on_delete=models.CASCADE, blank=True)

    def __str__(self):
        return self.city_name

データの登録

1.管理画面で適当にモデルにデータを登録する。

今回はテストなのでこんな感じで登録した。

都道府県

市区町村

  1. 木更津、富津市は千葉県へ紐付ける
  2. 十和田市は青森県へ紐付ける
  3. 札幌市中央区は北海道へ紐付ける

Serializerの登録

Serializerの細かい作成方法は割愛します。
今回はPrefに紐付いているCity一覧を取得することを大目的にします。

from rest_framework import serializers
from .models import Pref, City, Plan


class CitySerializer(serializers.ModelSerializer):

    class Meta:
        model = City
        fields = ['id', 'city_name', 'city_code']


class PrefSerializer(serializers.ModelSerializer):

    city = serializers.SerializerMethodField()

    class Meta:
        model = Pref
        fields = ['id', 'pref_name', 'pref_code', 'city']

    def get_city(self, obj):
        try:
            city_child = CitySerializer(City.objects.all().filter(pref=Pref.objects.get(id=obj.id)),many=True).data
            return city_child
        except:
            city_child = None
            return city_child


ポイント

  1. PrefSerializerにcity = serializers.SerializerMethodField()を追加すること
  2. 子要素のcityオブジェクトを def get_cityとして取得することです。

以下コードはCitySerializerからcityオブジェクト一覧を取得し、フィルターで関連するPrefオブジェクトを取得しています。
最後に,.data をつけないとエラーになります。

city_child = CitySerializer(City.objects.all().filter(pref=Pref.objects.get(id=obj.id)),many=True).data

View

今回はAPIViewを継承して一覧を取得しました。

from django_filters import rest_framework as filters
from rest_framework import status, views
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError

from .models import Pref, City
from .serializer import PrefSerializer, PlanSerializer, CitySerializer

class PrefFilter(filters.FilterSet):

    class Meta:
        model = Pref
        fields = '__all__'


class PrefListApiView(views.APIView):

    def get(self, request, *args, **kwargs):
        #Prefオブジェクトを取得
        filter_set = PrefFilter(request.query_params, queryset=Pref.objects.all()) 
        #バリデーション
        if not filter_set.is_valid():
            raise ValidationError(filter_set.errors)

     #serializerインスタンスの作成
        serializer = PrefSerializer(instance=filter_set.qs, many=True)
        # serializerをレスポンス
        return Response(serializer.data, status.HTTP_200_OK)

結果はこんな感じ

city_code入れるの忘れた...

ありがとうございました。