Django REST framework로 중첩 된 리소스의 list 메소드
13997 단어 django-rest-framework파이썬api
환경
파이썬 3.8.2
장고 3.0.5
djangorestframework 3.11.0
모델
Parent
├ Child1
└ Child2
↑이런 관계의 모델의 경우
models.pyfrom django.db import models
class Parent(models.Model):
"""
親のモデル
"""
parent_column = models.CharField(
max_length=10, verbose_name='親モデルのカラム')
def __self__(self):
return self.parent_column
class Child1(models.Model):
"""
子供のモデル1
"""
# related_nameとserializerのfield名を合わせる
parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='child1s')
child1_column = models.CharField(
max_length=10, verbose_name='子モデル1のカラム')
def __self__(self):
return self.Child1_column
class Child2(models.Model):
"""
子供のモデル2
"""
# related_nameとserializerのfield名を合わせる
parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='child2s')
child2_column = models.CharField(
max_length=10, verbose_name='子モデル2のカラム')
def __self__(self):
return self.Child2_column
시리얼라이저
모델과 동일한 구성으로
models.pyfrom rest_framework import serializers
from .models import Parent, Child1, Child2
class Child1Serializer(serializers.ModelSerializer):
"""
子供のserializer1
"""
class Meta:
model = Child1
fields = [
'id',
'child1_column',
]
class Child2Serializer(serializers.ModelSerializer):
"""
子供のserializer2
"""
class Meta:
model = Child2
fields = [
'id',
'child2_column',
]
class ParentSerializer(serializers.ModelSerializer):
"""
親のserializer
"""
# 子供のserializerを親のfieldとして定義
# このfield名とmodelのrelated_nameを合わせる
child1s = Child1Serializer(many=True, read_only=True)
child2s = Child2Serializer(many=True, read_only=True)
class Meta:
model = Parent
fields = [
'id',
'parent_column',
'child1s',
'child2s',
]
보기
QuerySet는 나중에 괴롭히기 쉽도록, get_queryset()로 정의해 두는 것이 좋을 것 같다.
views.pyfrom rest_framework import generics
from rest_framework.pagination import PageNumberPagination
from .models import Parent
from .serializer import ParentSerializer
class NestedListView(generics.ListAPIView):
"""
ネストしたリソースのlistメソッド
listだけ使いたいのでgenerics.ListAPIViewを使用
"""
pagination_class = PageNumberPagination
serializer_class = ParentSerializer
# クエリ―パラメータをfilterの検索条件に変換するdict
CONDITION_KEYS = {
'parent_column': 'parent_column__contains',
'child1_column': 'child1s__child1_column__contains',
'child2_column': 'child2s__child2_column__contains',
}
def get_queryset(self):
"""
後々、複雑なQuerySetを書くことになるかもしれないので、
ゴニョゴニョできる場所で定義しておく。
"""
# 検索条件のdict
condition_dict = {}
for key, val in self.request.query_params.items():
# query_paramsのkeyに検索条件の項目があったらfilter用のkeyに変換する
if key in self.CONDITION_KEYS:
condition_dict[self.CONDITION_KEYS[key]] = val
queryset = Parent.objects.filter(**condition_dict).order_by('id').prefetch_related().distinct()
return queryset
def list(self, request, *args, **kwargs):
"""
listメソッドをオーバライド
"""
# querysetにpaginationを適用
page_qs = self.paginate_queryset(self.get_queryset())
# serializeを取得
serializer = self.get_serializer(page_qs, many=True)
# paginationつきで返却
return self.get_paginated_response(serializer.data)
API 실행 결과
이런 느낌
간단했습니다.
출처
참고문헌
Parent
├ Child1
└ Child2
↑이런 관계의 모델의 경우
models.py
from django.db import models
class Parent(models.Model):
"""
親のモデル
"""
parent_column = models.CharField(
max_length=10, verbose_name='親モデルのカラム')
def __self__(self):
return self.parent_column
class Child1(models.Model):
"""
子供のモデル1
"""
# related_nameとserializerのfield名を合わせる
parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='child1s')
child1_column = models.CharField(
max_length=10, verbose_name='子モデル1のカラム')
def __self__(self):
return self.Child1_column
class Child2(models.Model):
"""
子供のモデル2
"""
# related_nameとserializerのfield名を合わせる
parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='child2s')
child2_column = models.CharField(
max_length=10, verbose_name='子モデル2のカラム')
def __self__(self):
return self.Child2_column
시리얼라이저
모델과 동일한 구성으로
models.pyfrom rest_framework import serializers
from .models import Parent, Child1, Child2
class Child1Serializer(serializers.ModelSerializer):
"""
子供のserializer1
"""
class Meta:
model = Child1
fields = [
'id',
'child1_column',
]
class Child2Serializer(serializers.ModelSerializer):
"""
子供のserializer2
"""
class Meta:
model = Child2
fields = [
'id',
'child2_column',
]
class ParentSerializer(serializers.ModelSerializer):
"""
親のserializer
"""
# 子供のserializerを親のfieldとして定義
# このfield名とmodelのrelated_nameを合わせる
child1s = Child1Serializer(many=True, read_only=True)
child2s = Child2Serializer(many=True, read_only=True)
class Meta:
model = Parent
fields = [
'id',
'parent_column',
'child1s',
'child2s',
]
보기
QuerySet는 나중에 괴롭히기 쉽도록, get_queryset()로 정의해 두는 것이 좋을 것 같다.
views.pyfrom rest_framework import generics
from rest_framework.pagination import PageNumberPagination
from .models import Parent
from .serializer import ParentSerializer
class NestedListView(generics.ListAPIView):
"""
ネストしたリソースのlistメソッド
listだけ使いたいのでgenerics.ListAPIViewを使用
"""
pagination_class = PageNumberPagination
serializer_class = ParentSerializer
# クエリ―パラメータをfilterの検索条件に変換するdict
CONDITION_KEYS = {
'parent_column': 'parent_column__contains',
'child1_column': 'child1s__child1_column__contains',
'child2_column': 'child2s__child2_column__contains',
}
def get_queryset(self):
"""
後々、複雑なQuerySetを書くことになるかもしれないので、
ゴニョゴニョできる場所で定義しておく。
"""
# 検索条件のdict
condition_dict = {}
for key, val in self.request.query_params.items():
# query_paramsのkeyに検索条件の項目があったらfilter用のkeyに変換する
if key in self.CONDITION_KEYS:
condition_dict[self.CONDITION_KEYS[key]] = val
queryset = Parent.objects.filter(**condition_dict).order_by('id').prefetch_related().distinct()
return queryset
def list(self, request, *args, **kwargs):
"""
listメソッドをオーバライド
"""
# querysetにpaginationを適用
page_qs = self.paginate_queryset(self.get_queryset())
# serializeを取得
serializer = self.get_serializer(page_qs, many=True)
# paginationつきで返却
return self.get_paginated_response(serializer.data)
API 실행 결과
이런 느낌
간단했습니다.
출처
참고문헌
from rest_framework import serializers
from .models import Parent, Child1, Child2
class Child1Serializer(serializers.ModelSerializer):
"""
子供のserializer1
"""
class Meta:
model = Child1
fields = [
'id',
'child1_column',
]
class Child2Serializer(serializers.ModelSerializer):
"""
子供のserializer2
"""
class Meta:
model = Child2
fields = [
'id',
'child2_column',
]
class ParentSerializer(serializers.ModelSerializer):
"""
親のserializer
"""
# 子供のserializerを親のfieldとして定義
# このfield名とmodelのrelated_nameを合わせる
child1s = Child1Serializer(many=True, read_only=True)
child2s = Child2Serializer(many=True, read_only=True)
class Meta:
model = Parent
fields = [
'id',
'parent_column',
'child1s',
'child2s',
]
QuerySet는 나중에 괴롭히기 쉽도록, get_queryset()로 정의해 두는 것이 좋을 것 같다.
views.py
from rest_framework import generics
from rest_framework.pagination import PageNumberPagination
from .models import Parent
from .serializer import ParentSerializer
class NestedListView(generics.ListAPIView):
"""
ネストしたリソースのlistメソッド
listだけ使いたいのでgenerics.ListAPIViewを使用
"""
pagination_class = PageNumberPagination
serializer_class = ParentSerializer
# クエリ―パラメータをfilterの検索条件に変換するdict
CONDITION_KEYS = {
'parent_column': 'parent_column__contains',
'child1_column': 'child1s__child1_column__contains',
'child2_column': 'child2s__child2_column__contains',
}
def get_queryset(self):
"""
後々、複雑なQuerySetを書くことになるかもしれないので、
ゴニョゴニョできる場所で定義しておく。
"""
# 検索条件のdict
condition_dict = {}
for key, val in self.request.query_params.items():
# query_paramsのkeyに検索条件の項目があったらfilter用のkeyに変換する
if key in self.CONDITION_KEYS:
condition_dict[self.CONDITION_KEYS[key]] = val
queryset = Parent.objects.filter(**condition_dict).order_by('id').prefetch_related().distinct()
return queryset
def list(self, request, *args, **kwargs):
"""
listメソッドをオーバライド
"""
# querysetにpaginationを適用
page_qs = self.paginate_queryset(self.get_queryset())
# serializeを取得
serializer = self.get_serializer(page_qs, many=True)
# paginationつきで返却
return self.get_paginated_response(serializer.data)
API 실행 결과
이런 느낌
간단했습니다.
출처
참고문헌
참고문헌
그 밖에도 본 것 같지만 잊었다…
Reference
이 문제에 관하여(Django REST framework로 중첩 된 리소스의 list 메소드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ping2shi2/items/805113d68860b540ad52텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)