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

如何在Django RestFramework中实现一对多关系?附示例需求

Alright, let's get your one-to-many relationship set up to match that exact JSON structure you're aiming for. Here's how to tweak your existing model.py and serializers.py step by step:

1. Update your models.py

We'll define two models: Product (the "one" side of the relationship) and TaxDetail (the "many" side, each linked to a single product). The foreign key goes on the TaxDetail model, and we'll set a related_name to make it easy to pull all tax details for a product later.

from django.db import models

class Product(models.Model):
    product_name = models.CharField(max_length=255)
    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 TaxDetail(models.Model):
    # Link each tax detail to a single product
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='tax_details')
    tax_name = models.CharField(max_length=255)
    percentage = models.DecimalField(max_digits=5, decimal_places=2)

    def __str__(self):
        return f"{self.tax_name} - {self.percentage}%"

The related_name='tax_details' is key here—it lets us access all linked tax records directly from a Product instance, which is critical for the nested JSON output.

2. Update your serializers.py

We'll create two serializers: one for TaxDetail (to format each tax entry correctly, including the URL) and one for Product that nests the tax details serializer.

from rest_framework import serializers
from .models import Product, TaxDetail
from django.urls import reverse

class TaxDetailSerializer(serializers.ModelSerializer):
    # Dynamically generate the tax detail URL
    tax_name = serializers.SerializerMethodField()

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

    def get_tax_name(self, obj):
        # Build the absolute URL using the request context (if available)
        request = self.context.get('request')
        if request:
            return request.build_absolute_uri(reverse('tax-detail', kwargs={'pk': obj.pk}))
        # Fallback to relative URL if request isn't passed in
        return f"/tax/{obj.pk}/"

class ProductSerializer(serializers.ModelSerializer):
    # Nest the tax details serializer to show all related entries
    tax_details = TaxDetailSerializer(many=True, read_only=True)

    class Meta:
        model = Product
        fields = ['id', 'product_name', 'description', 'sales', 'cost', 'tax_details']

Quick breakdown:

  • SerializerMethodField for tax_name generates the exact URL format you need, using Django's reverse to match your route structure.
  • TaxDetailSerializer(many=True) tells the product serializer to expect and format multiple tax entries for a single product.
3. Quick Setup for Views & URLs (to make it work end-to-end)

To get the full working endpoint, you'll need to set up basic views and routes:

Example views.py

from rest_framework import viewsets
from .models import Product, TaxDetail
from .serializers import ProductSerializer, TaxDetailSerializer

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

class TaxDetailViewSet(viewsets.ModelViewSet):
    queryset = TaxDetail.objects.all()
    serializer_class = TaxDetailSerializer

Example urls.py

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

router = DefaultRouter()
router.register(r'products', ProductViewSet)
# Set basename to ensure the route name matches what we used in the serializer
router.register(r'tax', TaxDetailViewSet, basename='tax')

urlpatterns = [
    path('', include(router.urls)),
]
Test the Output

Once you create a Product and link some TaxDetail entries to it, hitting the product detail endpoint (e.g., http://127.0.0.1:8000/products/1/) will return exactly the JSON structure you wanted:

{
  "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": 2.00
    }
  ]
}

内容的提问来源于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 06:16:10