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

如何在Django REST Framework中实现一对多嵌套关联?附模型与预期输出

没问题,我来帮你一步步实现Django REST Framework里的一对多嵌套关联,刚好匹配你想要的输出格式。先从模型定义开始,再到序列化器、视图,最后验证效果。

1. 完善模型定义(models.py)

首先得确保你的Product和Tax模型是一对多关系(一个商品对应多个税项),所以在Tax模型里要添加外键关联Product,并且设置related_name为tax_details,这样后续序列化时能直接通过这个名称获取关联的税项:

from django.db import models

class Product(models.Model):
    product_name = models.CharField(max_length=100)
    description = models.TextField()
    sales = models.DecimalField(max_digits=10, decimal_places=2)
    cost = models.DecimalField(max_digits=10, decimal_places=2)

    def __str__(self):
        return self.product_name

class Tax(models.Model):
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE,
        related_name='tax_details'  # 这个名称要和你预期输出里的字段名一致
    )
    tax_name = models.CharField(max_length=50)
    percentage = models.DecimalField(max_digits=5, decimal_places=2)

    def __str__(self):
        return f"{self.tax_name} - {self.percentage}%"
2. 编写嵌套序列化器(serializers.py)

接下来要写序列化器,这里需要嵌套序列化:先定义TaxSerializer处理单个税项的序列化,然后在ProductSerializer里用它来序列化关联的多个税项集合。另外你预期里的tax_name是API URL,所以我们用HyperlinkedIdentityField来生成对应的详情URL:

from rest_framework import serializers
from .models import Product, Tax

class TaxSerializer(serializers.ModelSerializer):
    # 生成税项的详情URL,对应你预期里的tax_name字段
    tax_name = serializers.HyperlinkedIdentityField(
        view_name='tax-detail',  # 这个要和你urls里定义的税项详情视图名称一致
        lookup_field='pk'
    )

    class Meta:
        model = Tax
        fields = ['id', 'tax_name', 'percentage']

class ProductSerializer(serializers.ModelSerializer):
    # 嵌套序列化关联的税项,many=True表示是多个对象,read_only=True表示只用于序列化输出
    tax_details = TaxSerializer(many=True, read_only=True)

    class Meta:
        model = Product
        fields = ['id', 'product_name', 'description', 'sales', 'cost', 'tax_details']
3. 配置视图和路由

视图部分(views.py)

用ModelViewSet来快速实现商品的列表、详情接口,税项的接口也可以用同样的方式:

from rest_framework import viewsets
from .models import Product, Tax
from .serializers import ProductSerializer, TaxSerializer

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

class TaxViewSet(viewsets.ModelViewSet):
    queryset = Tax.objects.all()
    serializer_class = TaxSerializer

路由部分(urls.py)

配置路由,注意要给税项的详情视图设置名称tax-detail,和序列化器里的view_name对应:

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet, TaxViewSet

router = DefaultRouter()
router.register(r'products', ProductViewSet)
router.register(r'tax', TaxViewSet, basename='tax')  # basename用来生成视图名称,这里会生成tax-detail

urlpatterns = [
    path('', include(router.urls)),
]
4. 验证效果

现在你可以创建一些测试数据:先创建Product,再创建关联它的Tax记录,然后访问http://127.0.0.1:8000/products/1/(假设商品id是1),就能得到你想要的输出格式:

{
    "id": 1,
    "product_name": "Rice",
    "description": "expired on 13-04-2018",
    "sales": "55.00",
    "cost": "55.00",
    "tax_details": [
        {
            "id": 1,
            "tax_name": "http://127.0.0.1:8000/tax/1/",
            "percentage": "10.00"
        },
        {
            "id": 2,
            "tax_name": "http://127.0.0.1:8000/tax/3/",
            "percentage": "20.00"
        }
    ]
}
关键注意点
  • related_name必须和你预期输出里的嵌套字段名(tax_details)一致,这样DRF才能找到关联的税项数据。
  • 嵌套序列化器的many=True是必须的,因为一个商品对应多个税项,是集合类型。
  • HyperlinkedIdentityField的view_name要和路由里生成的详情视图名称完全匹配,否则会生成不了URL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:31:54