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

Django REST中通过序列化器获取ManyToManyField关联值求助

Django多对多关联数据在通用视图中的获取方案

嘿,我刚看到你的问题啦!作为Django老玩家,太懂新手遇到多对多关联数据获取的困惑了😉 别急,咱们一步步来搞定它,正好prefetch_related就是解决这个问题的关键,我给你详细讲讲具体操作:

先确认你的模型结构(参考示例)

首先我假设你的模型大概是这样的,如果有调整可以对应修改:

from django.db import models

class Service(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)  # 示例字段,按你的实际字段调整

class Owner(models.Model):
    id = models.AutoField(primary_key=True)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    services = models.ManyToManyField(Service, related_name='owners')

方案1:用Django REST Framework(推荐,输出JSON更省心)

如果你的项目是做API,用DRF会非常方便:

第一步:定义序列化器

序列化器负责把模型数据转成你要的JSON格式:

from rest_framework import serializers

class ServiceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Service
        fields = ('id', 'name')  # 这里写你需要返回的Service字段

class OwnerSerializer(serializers.ModelSerializer):
    # 序列化关联的多个Service,many=True表示是多对多关系
    services = ServiceSerializer(many=True)

    class Meta:
        model = Owner
        fields = ('id', 'first_name', 'last_name', 'services')

第二步:写通用视图

用ListAPIView这个通用视图,加上prefetch_related预加载关联数据:

from rest_framework.generics import ListAPIView
from .models import Owner

class OwnerListView(ListAPIView):
    # 关键!用prefetch_related预加载services,避免N+1查询
    queryset = Owner.objects.all().prefetch_related('services')
    serializer_class = OwnerSerializer

启动项目访问这个视图,就能得到你想要的格式啦,比如:

[
    {
        "id": 1,
        "first_name": "james",
        "last_name": "cook",
        "services": [
            {"id": 1, "name": "清洁服务"},
            {"id": 2, "name": "维修服务"}
        ]
    }
]

方案2:不用DRF,手动构造JSON返回

如果不用DRF,用普通的通用视图也能实现:

from django.http import JsonResponse
from django.views.generic import View
from .models import Owner

class OwnerJsonView(View):
    def get(self, request):
        # 同样用prefetch_related预加载services
        owners = Owner.objects.all().prefetch_related('services')
        result_data = []
        
        for owner in owners:
            # 手动构造每个Owner的字典数据
            owner_item = {
                "owner_id": owner.id,
                "first_name": owner.first_name,
                "last_name": owner.last_name,
                "services": [
                    {"service_id": service.id, "service_name": service.name} 
                    for service in owner.services.all()
                ]
            }
            result_data.append(owner_item)
        
        return JsonResponse(result_data, safe=False)

重点提醒

  • prefetch_related是专门用来处理多对多、反向外键这类跨表关联的预加载,能避免循环每个Owner时都查询一次Services的性能问题(也就是常说的N+1查询)。
  • 如果你需要返回Service的其他字段,直接在构造字典或者序列化器里添加对应的字段名就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:50:40