如何在Django Generics中重写get_queryset查询指定Note的关联Blocks?
解决方案
一、先修正序列化器代码
你的序列化器存在两处问题,先做修正:
- 反向关联名称错误:如果
Block模型中外键字段关联的是Note(比如note = models.ForeignKey(Note, on_delete=models.CASCADE)),默认反向关联名称是block_set,而非noteblock_set。 get_blocks方法缺失返回值:自定义字段的get方法必须返回序列化后的数据,否则无法正确渲染关联内容。
修正后的序列化器代码:
class BlockSerializer(serializers.ModelSerializer): class Meta: model = Block fields = ['id', 'text'] class NoteSerializer(serializers.ModelSerializer): blocks = BlockSerializer(many=True, read_only=True) class Meta: model = Notes fields = ['id', 'header', 'user', 'blocks', 'created_at'] read_only_fields = ['created_at'] def get_blocks(self, obj): # 按order排序后序列化返回关联的Block note_blocks = obj.block_set.all().order_by('order') return BlockSerializer(note_blocks, many=True).data
更简洁的优化方式:直接在Block模型的外键字段添加related_name='blocks',这样无需编写get_blocks方法,Django会自动处理反向关联:
# models.py 中的 Block 模型 class Block(models.Model): note = models.ForeignKey(Notes, on_delete=models.CASCADE, related_name='blocks') text = models.TextField() order = models.IntegerField() # 其他字段...
二、重写BlockCreate视图的get_queryset方法
要获取指定Note下的所有Block,需要从URL中获取Note的主键参数,再过滤关联数据。
1. 配置URL路由
确保URL中包含Note的主键参数,示例:
# urls.py path('notes/<int:note_pk>/blocks/', BlockCreate.as_view(), name='note-blocks')
2. 重写视图方法
class BlockCreate(generics.ListCreateAPIView): serializer_class = BlockSerializer permission_classes = [IsAuthenticated] def get_queryset(self): # 从URL参数中提取note_pk,过滤出属于该Note且属于当前用户的Block note_pk = self.kwargs.get('note_pk') return Block.objects.filter(note__id=note_pk, note__user=self.request.user) def perform_create(self, serializer): # 创建Block时自动关联到指定Note,无需前端传递note参数 note_pk = self.kwargs.get('note_pk') note = Notes.objects.get(id=note_pk, user=self.request.user) serializer.save(note=note)
三、NoteCreate视图的get_queryset重写(可选)
如果需要该视图只返回当前登录用户的所有Note,重写方法如下:
class NoteCreate(generics.ListCreateAPIView): serializer_class = NoteSerializer permission_classes = [IsAuthenticated] def perform_create(self, serializer): # 创建Note时自动关联当前用户 serializer.save(user=self.request.user) def get_queryset(self): # 仅返回当前用户的Note return Notes.objects.filter(user=self.request.user)
内容的提问来源于stack exchange,提问作者sbnd abhijeet
相关产品推荐
相关产品推荐

