Django多对多关系的反序列化及指定JSON结构实现方法
Hey there! Let's walk through how to build that exact JSON output you need. First, I spotted a small typo in your Product model's many-to-many field—you currently have:
category = models.name = models.ManyToManyField(Category)
That should be simplified to:
category = models.ManyToManyField(Category)
This fixes the invalid field definition and ensures the many-to-many relationship works correctly.
Now, here are two reliable approaches to generate your target JSON:
Approach 1: Use Django REST Framework (DRF) Serializers
If you're using DRF (the standard tool for Django API development), this is the cleanest method:
Step 1: Create Serializers
Create a serializers.py file in your app with these serializers:
from rest_framework import serializers from .models import Category, Product # Serializer to format product data into your desired "name" and "code" fields class ProductMiniSerializer(serializers.ModelSerializer): code = serializers.CharField(source='product_code') # Maps product_code to "code" in JSON class Meta: model = Product fields = ['name', 'code'] # Serializer for categories, including related products class CategorySerializer(serializers.ModelSerializer): # Use source='product_set' to access the reverse many-to-many relationship products = ProductMiniSerializer(many=True, source='product_set') class Meta: model = Category fields = ['id', 'name', 'description', 'products']
Step 2: Build a View to Return the JSON
Add this view to your views.py:
from rest_framework.response import Response from rest_framework.decorators import api_view from .models import Category from .serializers import CategorySerializer @api_view(['GET']) def categories_with_products(request): # Use prefetch_related to avoid N+1 database queries (critical for performance) categories = Category.objects.prefetch_related('product_set').all() serializer = CategorySerializer(categories, many=True) # Wrap the serialized data in the "categories" top-level key return Response({"categories": serializer.data})
Note: Your sample JSON shows a single products object per category, but since it's a many-to-many relationship, a category can have multiple products. The above code returns products as an array of objects (which is more logical for this relationship). If you specifically need one product per category (e.g., the first one), replace many=True with a custom serializer method:
# Inside CategorySerializer products = serializers.SerializerMethodField() def get_products(self, obj): product = obj.product_set.first() if product: return ProductMiniSerializer(product).data return {}
Approach 2: Manual JSON Construction (No DRF)
If you don't want to use DRF, you can manually build the dictionary and return it as JSON:
Add this view to your views.py:
from django.http import JsonResponse from .models import Category def categories_with_products(request): categories_list = [] # Prefetch related products to optimize database queries categories = Category.objects.prefetch_related('product_set').all() for category in categories: # Get the first product (adjust this if you need all products) product = category.product_set.first() product_data = { "name": product.name, "code": product.product_code } if product else {} category_data = { "id": category.id, "name": category.name, "description": category.description, "products": product_data } categories_list.append(category_data) return JsonResponse({"categories": categories_list})
Key Notes for Both Approaches
- Always use
prefetch_related('product_set')when querying categories—this fetches all related products in a single query instead of one query per category (avoids the N+1 performance issue). - Handle cases where a category has no products (return an empty
productsobject instead of causing an error).
内容的提问来源于stack exchange,提问作者amit

