序列化 关联对象
在 Django 中,模型之间经常存在关联关系(一对一、一对多、多对多);当需要将这些模型序列化为 JSON 或其他格式时,DRF 提供了3种处理关联对象的方式
PrimaryKeyRelatedField(主键关联字段)
作用:将关联对象序列化为它们的主键值
特点:1.简单直接,只显示关联对象的主键
2.需要指定 read_only=True或queryset参数
3.many=True表示一对多或多对多关系
场景:只需要关联对象的 ID;前端可以通过这些 ID 再发起请求获取详细信息
示例:
模型定义
from django.db import modelsclass Author(models.Model): name = models.CharField(max_length=100) email = models.EmailField()def __str__(self):return self.nameclass Book(models.Model): title = models.CharField(max_length=200) published_date = models.DateField() author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)def __str__(self):return self.title
序列化器定义
from rest_framework import serializersfrom .models import Author, Bookclass AuthorSerializer(serializers.ModelSerializer): books = serializers.PrimaryKeyRelatedField(many=True, read_only=True)class Meta: model = Author fields = ['id', 'name', 'email', 'books']class BookSerializer(serializers.ModelSerializer):class Meta: model = Book fields = ['id', 'title', 'published_date', 'author']
视图定义
from rest_framework import genericsfrom .models import Author, Bookfrom .serializers import AuthorSerializer, BookSerializerclass AuthorListCreateView(generics.ListCreateAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializerclass BookListCreateView(generics.ListCreateAPIView): queryset = Book.objects.all() serializer_class = BookSerializer
输出结果
{"id": 1,"name": "J.K. Rowling","email": "jk@example.com","books": [1, 2, 3]}
使用关联对象的序列化器(嵌套序列化)
作用:将关联对象完全序列化,包含所有字段
特点:1.显示关联对象的完整信息
2.需要定义关联对象的序列化器
3.可能导致数据嵌套层级较深
场景:需要一次性获取所有关联对象的详细信息;关联对象的数据量不大
示例:
模型定义
from django.db import modelsclass Author(models.Model): name = models.CharField(max_length=100) email = models.EmailField()def __str__(self):return self.nameclass Book(models.Model): title = models.CharField(max_length=200) published_date = models.DateField() author = models.ForeignKey(Author, related_name='books', on_delete=models.CASCADE)def __str__(self):return self.title
序列化器定义
from rest_framework import serializersfrom .models import Author, Bookclass BookSerializer(serializers.ModelSerializer):class Meta: model = Book fields = ['id', 'title', 'published_date']class AuthorSerializer(serializers.ModelSerializer): books = BookSerializer(many=True, read_only=True)class Meta: model = Author fields = ['id', 'name', 'email', 'books']
视图定义
from rest_framework import genericsfrom .models import Author, Bookfrom .serializers import AuthorSerializer, BookSerializerclass AuthorListCreateView(generics.ListCreateAPIView): queryset = Author.objects.all() serializer_class = AuthorSerializerclass BookListCreateView(generics.ListCreateAPIView): queryset = Book.objects.all() serializer_class = BookSerializer
输出结果
{"id": 1,"name": "J.K. Rowling","email": "jk@example.com","books": [ {"id": 1,"title": "Harry Potter 1","published_date": "1997-06-26" }, {"id": 2,"title": "Harry Potter 2","published_date": "1998-07-02" } ]}
StringRelatedField(字符串关联字段)
作用:将关联对象序列化为它们的 str方法的返回值
特点:1.依赖模型的 str方法
2.只读字段(不能用于反序列化)
3.显示格式有模型定义决定
场景:只需要显示关联对象的简单字符串表示;不需要完整的对象信息
示例:
模型定义
from django.db import modelsclass Department(models.Model): name = models.CharField(max_length=100) location = models.CharField(max_length=100)def __str__(self):returnf"{self.name} ({self.location})"class Employee(models.Model): name = models.CharField(max_length=100) position = models.CharField(max_length=100) department = models.ForeignKey(Department, related_name='employees', on_delete=models.CASCADE)def __str__(self):returnf"{self.name} - {self.position}"
序列化器定义
from rest_framework import serializersfrom .models import Department, Employeeclass DepartmentSerializer(serializers.ModelSerializer): employees = serializers.StringRelatedField(many=True)class Meta: model = Department fields = ['id', 'name', 'location', 'employees']class EmployeeSerializer(serializers.ModelSerializer):class Meta: model = Employee fields = ['id', 'name', 'position', 'department']
视图定义
from rest_framework import genericsfrom .models import Department, Employeefrom .serializers import DepartmentSerializer, EmployeeSerializerclass DepartmentListCreateView(generics.ListCreateAPIView): queryset = Department.objects.all() serializer_class = DepartmentSerializerclass EmployeeListCreateView(generics.ListCreateAPIView): queryset = Employee.objects.all() serializer_class = EmployeeSerializer
输出结果
{"id": 1,"name": "Engineering","location": "Floor 5","employees": ["John Doe - Software Engineer","Jane Smith - Senior Developer" ]}