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

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


# 前提

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

1. Prefは都道府県
1. Cityは市区町村を指す


```py
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

```

## データの登録
１．管理画面で適当にモデルにデータを登録する。

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

### 都道府県

![スクリーンショット 2021-04-21 18.29.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/3552563b-30d6-d5e0-bc7a-5c87aac45cac.png)

### 市区町村

![スクリーンショット 2021-04-21 18.30.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/98209ade-6488-9eda-3cff-6e5ad696383c.png)

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

## Serializerの登録

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

```py
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`　をつけないとエラーになります。

```py
city_child = CitySerializer(City.objects.all().filter(pref=Pref.objects.get(id=obj.id)),many=True).data
```
## View
今回はAPIViewを継承して一覧を取得しました。

```py
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)
```

## 結果はこんな感じ

![スクリーンショット 2021-04-21 18.44.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/2da5cf94-6846-f7f6-cbe3-110b498ec7f4.png)


city_code入れるの忘れた...


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