基于Django Rest Framework的API开发:特定JSON格式化查询需求
Hey there! Let's figure out how to format your Unit and Location model data into that specific JSON structure with Django Rest Framework. Here are the most practical, DRF-native solutions to get this done:
This is the standard way to handle data serialization in DRF—it’s flexible, maintainable, and plays nicely with DRF’s views and permissions.
Step 1: Define Serializers
First, create a serializer for your Location model that maps its name field to category_name as you need. Then nest it (or reference it) in the Unit serializer.
Option A: Nested Location Data
If you want the category_name wrapped inside a location object in your JSON:
from rest_framework import serializers from .models import Unit, Location class LocationSerializer(serializers.ModelSerializer): # Map Location.name to category_name in the response category_name = serializers.CharField(source='name', read_only=True) class Meta: model = Location fields = ['category_name'] class UnitSerializer(serializers.ModelSerializer): # Nest the LocationSerializer to include category_name location = LocationSerializer(read_only=True) class Meta: model = Unit fields = ['name', 'summary', 'location']
Option B: Flat JSON Structure
If you want category_name to be a top-level field alongside name and summary:
class UnitSerializer(serializers.ModelSerializer): # Pull Location.name directly as a top-level field category_name = serializers.CharField(source='location.name', read_only=True) class Meta: model = Unit fields = ['name', 'summary', 'category_name']
Step 2: Create a View to Return Serialized Data
Use a DRF generic view to handle fetching and serializing your Unit data. Don’t forget to use select_related to avoid costly N+1 database queries!
from rest_framework.generics import ListAPIView from .models import Unit from .serializers import UnitSerializer class UnitListView(ListAPIView): # Pre-load related Location data to boost performance queryset = Unit.objects.all().select_related('location') serializer_class = UnitSerializer
Example Outputs
- For Option A (nested):
[ { "name": "Downtown Office", "summary": "Main headquarters", "location": { "category_name": "Urban" } } ]
- For Option B (flat):
[ { "name": "Downtown Office", "summary": "Main headquarters", "category_name": "Urban" } ]
Since your location field allows null values, add a safety check if you want to avoid errors or return a clean null instead:
class UnitSerializer(serializers.ModelSerializer): category_name = serializers.SerializerMethodField() def get_category_name(self, obj): # Return null if Location doesn't exist return obj.location.name if obj.location else None class Meta: model = Unit fields = ['name', 'summary', 'category_name']
values() for Simple Cases If you don’t need the full power of serializers (e.g., validation, permissions), you can directly construct the data with Django’s values() method:
from django.db.models import F from rest_framework.response import Response from rest_framework.views import APIView from .models import Unit class UnitListView(APIView): def get(self, request): units = Unit.objects.all().select_related('location').values( 'name', 'summary', # Map location__name to category_name category_name=F('location__name') ) return Response(units)
This will return the same flat JSON structure as Option B above.
内容的提问来源于stack exchange,提问作者Bheid

