深くネストされたデータ構造から文字列のリストを返せるようにしたい。このシナリオでは、さまざまな地域に多くの場所がある書店のチェーンを管理するAPIがあります。
現在、リージョンのIDを受け取り、リージョン、個々の書店、および各ストアにある本に関する詳細のネストされたJSON構造を返すAPIエンドポイントがあります。
{
"region": [
{
"store": [
{
"book": {
"name": "Foo"
}
},
{
"book": {
"name": "Bar"
}
},
{
"book": {
"name": "Baz"
}
}
],
},
{
"store": [
{
"book": {
"name": "Foo"
}
},
{
"book": {
"name": "Bar"
}
}
],
},
{
"store": [
{
"book": {
"name": "Foo"
}
},
{
"book": {
"name": "Baz"
}
},
{
"book": {
"name": "Qux"
}
}
]
}
]
}
私のモデルは次のようになります。これらのモデルは、この不自然な例では最も意味がないことを認識していますが、実際のコードを反映しています。
class Book(TimeStampedModel):
name = models.CharField(default="", max_length=512)
class Bookstore(TimeStampedModel):
value = models.CharField(default="", max_length=1024)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
class Region(TimeStampedModel):
stores = models.ManyToManyField(Bookstore)
class BookstoreChain(TimeStampedModel):
regions = models.ManyToManyField(Region)
上記の応答用に作成したシリアライザーは次のようになります。
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
class BookstoreSerializer(serializers.ModelSerializer):
books = BookSerializer()
class Meta:
model = Bookstore
fields = "__all__"
class RegionSerializer(serializers.ModelSerializer):
stores = BookstoreSerializer(many=True)
class Meta:
model = Region
fields = "__all__"
class BookstoreChainSerializer(serializers.ModelSerializer):
regions = RegionSerializer(many=True)
class Meta:
model = BookstoreChain
fields = "__all__"
このソリューションのビューまたはシリアライザーがどのように見える必要があるかわかりません。私は、生のSQLを記述したり、ORM / Linqを使用して一連の結果を取得したりすることに慣れています。
上記の応答が有用確実ですが、私が本当にしたいことは所与の領域で見つけることができ書籍名(のユニークなリストを返すためにAPIエンドポイントですFoo
、Bar
、Baz
、Qux
)。私の応答が次のようになることを願っています:
{
"books": [
"Foo",
"Bar",
"Baz",
"Qux"
]
}
これまでの私の弱い試みにurls.py
は、次のようなものがありますpath
。
path("api/regions/<int:pk>/uniqueBooks/", views.UniqueBooksForRegionView.as_view(), name="uniqueBooksForRegion")
私のviews.py
ように見えます:
class UniqueBooksForRegionView(generics.RetrieveAPIView):
queryset = Regions.objects.all()
serializer_class = ???
したがって、店舗を取得する必要がある地域から開始して、店舗内の本をフィルタリングできるようにします。これが機能するソリューションです。
リクエストにIDがない場合はエラーが発生するため.get()
、inの使用は避けてください。を使用できますが、Sentryにエラーを記録することはできません。*APIView
get_object_or_404()
から要素を取得するには*APIView
、を使用しますfilter()
。
import logging as L
class UniqueBooksForRegionView(generics.RetrieveAPIView):
lookup_field = 'pk'
def get(self, *args, **kwargs)
regions = Region.objects.filter(pk=self.kwargs[self.lookup_field])
if regions.exists():
region = regions.first()
stores_qs = region.stores.all()
books_qs = Book.objects.filter(store__in=stores_qs).distinct()
# use your book serializer
serializer = BookSerializer(books_qs, many=True)
return Response(serializer.data, HTTP_200_OK)
else:
L.error(f'Region with id {self.kwargs[self.lookup_field]} not found.')
return Response({'detail':f'Region with id {self.kwargs[self.lookup_field]} not found.'}, HTTP_404_NOT_FOUND)
これがフローです。コードを微調整する必要があるかもしれませんが、フローを理解するのに役立つことを願っています
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加