如何在Django REST Framework中获取含关联评论的书籍数据?
解决方法:获取Book数据时包含关联的Review评论
首先先修正你模型里的一个错误:Book类中重复定义了author字段(一个是CharField,一个是ForeignKey),这会导致Django报错,需要删除那个CharField类型的author字段。
接下来提供两种常用的实现方式:
方式一:使用Django REST Framework(DRF)序列化器嵌套(推荐)
如果你的项目用DRF来处理API请求,最简洁的方式是通过嵌套序列化器实现:
- 修正Book模型
class Book(models.Model): title = models.CharField(max_length=200, blank=False, null=False) # 移除重复的author CharField genres = models.ManyToManyField(Genre, related_name='genre', blank=True) author = models.ForeignKey(Author, related_name='author', blank=True, on_delete=models.CASCADE) description = models.TextField(max_length=1200, blank=False, default="This book doesn't have description yet!") image = models.ImageField(default="") created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) class Meta: ordering = ['created'] def __str__(self): return self.title
- 给Review模型设置更清晰的反向关联名
class Review(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, null=True) # 设置related_name为reviews,方便后续调用 book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name='reviews') title = models.CharField(max_length=100, null=False, blank=False, help_text="Title overall of your review") rating = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(5)], help_text='Rating in range 0-5') description = models.TextField(max_length=1000, null=False, blank=False) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True)
- 创建序列化器
from rest_framework import serializers from .models import Book, Review class ReviewSerializer(serializers.ModelSerializer): class Meta: model = Review fields = ['id', 'user', 'title', 'rating', 'description', 'created', 'updated'] class BookSerializer(serializers.ModelSerializer): # 直接嵌套评论序列化器,关联reviews字段 reviews = ReviewSerializer(many=True, read_only=True) class Meta: model = Book fields = ['id', 'title', 'author', 'genres', 'description', 'image', 'created', 'updated', 'reviews']
- 编写视图返回JSON
from rest_framework.views import APIView from rest_framework.response import Response from .models import Book from .serializers import BookSerializer class BookDetailAPI(APIView): def get(self, request, pk): # 预取评论,避免N+1查询 book = Book.objects.prefetch_related('reviews').get(pk=pk) serializer = BookSerializer(book) return Response(serializer.data)
方式二:手动构造JSON(无DRF场景)
如果不用DRF,可以手动查询并构造包含评论的JSON数据:
from django.http import JsonResponse from .models import Book def book_detail(request, pk): # 预取评论,提升查询效率 book = Book.objects.prefetch_related('reviews').get(pk=pk) # 构造书籍及评论数据 book_data = { 'id': book.id, 'title': book.title, 'author': book.author.name if book.author else None, 'description': book.description, 'genres': [genre.name for genre in book.genres.all()], 'created': book.created.isoformat(), 'updated': book.updated.isoformat(), 'reviews': [ { 'id': review.id, 'user': review.user.username if review.user else None, 'title': review.title, 'rating': review.rating, 'description': review.description, 'created': review.created.isoformat(), 'updated': review.updated.isoformat() } for review in book.reviews.all() ] } return JsonResponse(book_data)
内容的提问来源于stack exchange,提问作者Minh Anh
相关产品推荐
相关产品推荐

