Django ORM一对多关联查询:获取含书籍列表的出版社数据
Django ORM实现一对多关联嵌套序列化输出
可以通过Django ORM预加载关联数据+DRF嵌套序列化器实现需求,既避免N+1查询问题,又能生成符合预期的JSON结构。
1. 优化ORM查询(避免N+1问题)
由于是从主表Publication反向关联查询子表Book,使用prefetch_related预加载所有关联的书籍数据,减少数据库查询次数:
publications = Publication.objects.all().prefetch_related('books_publications')
注:
books_publications是你在Book模型中定义的related_name,对应反向关联的查询属性。
2. 编写DRF序列化器
定义两个序列化器:子表Book的基础序列化器,以及主表Publication的序列化器,通过嵌套子表序列化器生成嵌套结构:
from rest_framework import serializers from .models import Publication, Book class BookSerializer(serializers.ModelSerializer): class Meta: model = Book fields = ['id', 'name'] class PublicationSerializer(serializers.ModelSerializer): # 关联书籍列表,指定source为反向关联的related_name,输出字段名为'book' book = BookSerializer(many=True, source='books_publications') class Meta: model = Publication fields = ['id', 'name', 'book']
3. 视图中生成JSON数据
在视图中使用序列化器处理查询集,直接得到符合要求的JSON结构:
from rest_framework.views import APIView from rest_framework.response import Response from .models import Publication from .serializers import PublicationSerializer class PublicationListView(APIView): def get(self, request): # 预加载关联数据 publications = Publication.objects.all().prefetch_related('books_publications') # 序列化数据 serializer = PublicationSerializer(publications, many=True) # 返回JSON响应 return Response(serializer.data)
验证输出
运行视图后,返回的JSON结构将完全匹配你期望的格式:
[ { "id": 1, "name": "publication 001", "book": [ { "id": 1, "name": "Book 001" }, { "id": 2, "name": "Book 002" } ] }, { "id": 2, "name": "publication 002", "book": [ { "id": 3, "name": "Book 003" }, { "id": 4, "name": "Book 004" } ] } ]
额外说明
- 若不需要DRF,仅用Django原生序列化,可通过自定义
SerializerMethodField实现,但DRF的嵌套序列化器更简洁高效。 - 如需过滤关联的书籍数据(比如只返回特定状态的书籍),可使用
Prefetch对象自定义预加载的查询集:
from django.db.models import Prefetch # 假设Book有is_active字段,仅加载激活状态的书籍 filtered_books = Book.objects.filter(is_active=True) publications = Publication.objects.all().prefetch_related( Prefetch('books_publications', queryset=filtered_books) )
内容的提问来源于stack exchange,提问作者MD. SHIFULLAH
相关产品推荐
相关产品推荐

