Django Rest Framework:如何通过related_name填充ForeignKey并返回关联对象
解决Django REST Framework中外键返回完整关联对象的问题
看起来你已经找对了思路——通过嵌套序列化器来返回关联对象,只是代码里有几处细节错误导致没有达到预期效果。我帮你一步步修正并优化:
1. 修正模型中的引用错误
首先看你的models.py,BookModel的author字段引用了Author,但你的作者模型实际名为AuthorModel,这会直接导致模型找不到的错误。另外外键的default=''也不合理,因为外键存储的是UUID类型的ID,空字符串不是有效的值,应该改成null=True允许为空:
# models.py import uuid from django.db import models class AuthorModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField('Name', max_length=255) pen_name = models.CharField('Pen Name', max_length=255) class BookModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField('Book Name', max_length=255) # 修正模型引用,调整默认值和关联名称 author = models.ForeignKey(AuthorModel, on_delete=models.CASCADE, blank=True, null=True, related_name='books')
我还把related_name改成了更语义化的books,这样你可以通过author.books快速反向查询该作者的所有书籍。
2. 修正序列化器的模型引用
你的序列化器里同样犯了模型名称引用错误,把Author和Book改成实际的AuthorModel和BookModel即可,嵌套序列化器的写法是正确的:
# serializers.py from rest_framework import serializers from .models import AuthorModel, BookModel class AuthorSerializer(serializers.ModelSerializer): class Meta: model = AuthorModel fields = ('id', 'name', 'pen_name') class BookSerializer(serializers.ModelSerializer): # 嵌套AuthorSerializer,序列化时自动返回完整作者对象 author = AuthorSerializer() class Meta: model = BookModel fields = ('id', 'name', 'author')
3. 优化视图集的查询性能
为了避免查询书籍时出现N+1查询问题(每查一本书就单独查一次作者),可以用select_related预加载关联的作者数据,提升接口性能:
# views.py from rest_framework import viewsets, mixins from rest_framework.permissions import AllowAny from .models import BookModel from .serializers import BookSerializer class BookViewSet(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): # 预加载author关联对象,避免N+1查询 queryset = BookModel.objects.all().select_related('author') serializer_class = BookSerializer permission_classes = (AllowAny,)
预期效果
现在访问书籍详情接口时,返回的JSON会包含完整的作者对象,示例如下:
{ "id": "a1b2c3d4-5678-90ef-ghij-klmnopqrstuv", "name": "Python入门指南", "author": { "id": "wxyz-1234-5678-90ab-cdefghijklmn", "name": "张三", "pen_name": "码农张三" } }
如果需要支持创建书籍时同时创建作者,你还需要在BookSerializer中重写create方法来处理嵌套数据,但如果只是查询需求,上面的代码就完全够用了。
内容的提问来源于stack exchange,提问作者Goutam B Seervi
相关产品推荐
相关产品推荐

