You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 20:25:00