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

如何在Django Rest Framework中序列化关联Django模型?

Serializing Django Models with Foreign Keys in Django Rest Framework

Hey there! Let's walk through how to handle serialization for your models with foreign key relationships in DRF. I'll cover the most common approaches, from basic representations to writable nested serializers that work for create/update operations.

1. Basic Serializers (Default Foreign Key Handling)

First, let's start with simple serializers that use DRF's default behavior. By default, DRF serializes a foreign key as the primary key of the related object.

from rest_framework import serializers
from .models import Client, ClientDetail, ClientAssignment

class ClientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Client
        fields = ['id', 'name']

# ClientDetail with default foreign key (shows client ID)
class ClientDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientDetail
        fields = ['id', 'client', 'business_format']

# Assuming Assignment model exists, similar setup for ClientAssignment
class AssignmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Assignment
        fields = ['id', 'name']

class ClientAssignmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = ClientAssignment
        fields = ['id', 'client', 'assignment']

When you serialize a ClientDetail instance, the client field will return the ID of the associated Client (e.g., {"id": 1, "client": 2, "business_format": "Retail"}).

2. Customizing Foreign Key Representation

If you want more meaningful output instead of just an ID, here are a few practical options:

Option A: String Representation

Use StringRelatedField to display the string value from your model's __str__ method:

class ClientDetailSerializer(serializers.ModelSerializer):
    client = serializers.StringRelatedField()
    
    class Meta:
        model = ClientDetail
        fields = ['id', 'client', 'business_format']

This will output something like {"id":1, "client":"Acme Corp", "business_format":"Retail"}. Note this is read-only—you can't use it to create or update objects.

Option B: Nested Serializer

To include full details of the related object, nest its serializer:

class ClientDetailSerializer(serializers.ModelSerializer):
    client = ClientSerializer()
    
    class Meta:
        model = ClientDetail
        fields = ['id', 'client', 'business_format']

This will give you a nested object:

{
  "id": 1,
  "client": {"id":2, "name":"Acme Corp"},
  "business_format": "Retail"
}

This is read-only by default. To make it writable, see section 3 below.

Option C: Hyperlinked Relationship

If you prefer URLs to related objects, use HyperlinkedRelatedField:

class ClientDetailSerializer(serializers.ModelSerializer):
    client = serializers.HyperlinkedRelatedField(
        view_name='client-detail',  # Name of your Client detail view
        read_only=True
    )
    
    class Meta:
        model = ClientDetail
        fields = ['id', 'client', 'business_format']

This will output a URL like {"client": "/api/clients/2/"}.

3. Writable Serializers (Creating/Updating with Foreign Keys)

To create or update instances with foreign keys, you need to define how related objects are processed.

Using Primary Keys (Simple Writable Approach)

The easiest way is to use PrimaryKeyRelatedField with a queryset, which lets you pass the ID of an existing related object:

class ClientDetailSerializer(serializers.ModelSerializer):
    client = serializers.PrimaryKeyRelatedField(queryset=Client.objects.all())
    
    class Meta:
        model = ClientDetail
        fields = ['id', 'client', 'business_format']

Now you can create a ClientDetail by sending:

{
  "client": 2,
  "business_format": "Retail"
}

DRF will validate that the client ID exists before creating the instance.

Writable Nested Serializers

If you want to create a new Client at the same time as a ClientDetail, override the create method:

class ClientDetailSerializer(serializers.ModelSerializer):
    client = ClientSerializer()
    
    class Meta:
        model = ClientDetail
        fields = ['id', 'client', 'business_format']
    
    def create(self, validated_data):
        # Extract client data from validated input
        client_data = validated_data.pop('client')
        # Get or create the Client to avoid duplicates
        client, created = Client.objects.get_or_create(**client_data)
        # Create the ClientDetail with the associated client
        client_detail = ClientDetail.objects.create(client=client, **validated_data)
        return client_detail

Now you can send a nested JSON object to create both the Client and ClientDetail:

{
  "client": {"name": "New Client"},
  "business_format": "Wholesale"
}

For updates, you'd override the update method similarly, handling both the ClientDetail fields and nested Client data if needed.

4. Handling Reverse Relationships

If you want to include related ClientDetail or ClientAssignment instances in the Client serializer, first add a related_name to your model foreign keys (optional but recommended):

# Update your models
class ClientDetail(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='details')
    business_format = models.CharField(max_length=255)
    # ... rest of model

class ClientAssignment(models.Model):
    client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='assignments')
    assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
    # ... rest of model

Then include them in the Client serializer:

class ClientSerializer(serializers.ModelSerializer):
    details = ClientDetailSerializer(many=True, read_only=True)
    assignments = ClientAssignmentSerializer(many=True, read_only=True)
    
    class Meta:
        model = Client
        fields = ['id', 'name', 'details', 'assignments']

This will show all related ClientDetail and ClientAssignment instances when you serialize a Client.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:17:35