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

Django Rest Framework带中间表的多对多关系序列化问题

解决DRF多对多中间表字段及关联数据序列化问题

步骤1:确认模型关系(参考你的定义)

先明确模型间的关联逻辑,比如Human关联Company,Job和Human通过Connection中间表建立多对多:

# models.py
from django.db import models

class Company(models.Model):
    name = models.CharField(max_length=100)
    # 其他自定义字段

class Human(models.Model):
    name = models.CharField(max_length=100)
    company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='employees')
    # 其他自定义字段

class Job(models.Model):
    title = models.CharField(max_length=100)
    humans = models.ManyToManyField(Human, through='Connection', related_name='jobs')
    # 其他自定义字段

class Connection(models.Model):
    human = models.ForeignKey(Human, on_delete=models.CASCADE)
    job = models.ForeignKey(Job, on_delete=models.CASCADE)
    did_human_accept = models.BooleanField(default=False)
    did_job_accept = models.BooleanField(default=False)
    # 其他中间表自定义字段

步骤2:编写嵌套序列化器

通过多层嵌套序列化,把中间表字段、Human、关联的Company数据整合返回:

# serializers.py
from rest_framework import serializers
from .models import Company, Human, Job, Connection

# 先序列化Company基础数据
class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ['id', 'name']  # 按需指定字段,用__all__可返回全部字段

# 序列化Human时嵌套CompanySerializer,带出关联公司数据
class HumanSerializer(serializers.ModelSerializer):
    company = CompanySerializer()

    class Meta:
        model = Human
        fields = ['id', 'name', 'company']  # 按需指定字段

# 序列化中间表Connection,嵌套HumanSerializer并包含中间表自定义字段
class ConnectionSerializer(serializers.ModelSerializer):
    human = HumanSerializer()

    class Meta:
        model = Connection
        fields = ['id', 'did_human_accept', 'did_job_accept', 'human']  # 明确列出中间表字段和关联的Human

# 序列化Job时,通过中间表Connection返回整合后的数据
class JobSerializer(serializers.ModelSerializer):
    # source指定Job关联的Connection集合,默认反向关联名为connection_set
    connections = ConnectionSerializer(source='connection_set', many=True)

    class Meta:
        model = Job
        fields = ['id', 'title', 'connections']  # 包含Job自身字段和整合后的connections

步骤3:视图中优化查询(避免N+1性能问题)

查询Job时预加载所有关联数据,减少数据库查询次数:

# views.py
from rest_framework import viewsets
from .models import Job
from .serializers import JobSerializer

class JobViewSet(viewsets.ModelViewSet):
    # 预加载关联的中间表、Human、Company数据
    queryset = Job.objects.all().prefetch_related('connection_set__human__company')
    serializer_class = JobSerializer

关键注意点

  • 不能直接在JobSerializer中使用humans = HumanSerializer(many=True),这种方式只能返回Human数据,无法获取中间表的自定义字段。
  • 如果在Job的humans字段中设置了自定义related_name(比如related_name='connections'),则source参数需要改为source='connections'。

内容的提问来源于stack exchange,提问作者Arad Eytan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:56:18