Django REST Framework中如何为嵌套序列化器动态指定查询集
实现方案
我们可以通过DRF序列化器的上下文传递机制,结合动态过滤关联数据的方式实现需求,具体步骤如下:
第一步:修改ChapterSerializer,动态过滤关联Post
将原固定定义的嵌套Post序列化器替换为SerializerMethodField,通过自定义取值方法根据当前请求用户的权限过滤返回的Post数据,DRF视图会自动将请求对象注入到序列化器的context属性中,我们可以直接取用:
class ChapterSerializer(serializers.ModelSerializer): # 替换原固定嵌套序列化器为动态取值字段 post_set = serializers.SerializerMethodField() class Meta: model = Chapter fields = ['id', 'title', 'owner', 'post_set'] def get_post_set(self, chapter_obj): # 从序列化器上下文获取当前请求对象 request = self.context.get('request') # 无有效请求、或请求用户是当前章节所有者,返回所有关联Post if not request or request.user == chapter_obj.owner: filtered_posts = chapter_obj.post_set.all() # 非所有者仅返回未归档的Post else: filtered_posts = chapter_obj.post_set.filter(is_archived=False) # 传入上下文保证PostSerializer的超链接字段能正常生成 return PostSerializer(filtered_posts, many=True, context=self.context).data
第二步:(可选)优化查询性能
上述基础实现会触发N+1查询问题,我们可以在视图层添加预取逻辑提前加载关联数据,大幅提升接口响应速度:
from django.db.models import Prefetch class ChapterViewSet(viewsets.ModelViewSet): serializer_class = ChapterSerializer def get_queryset(self): current_user = self.request.user # 对非所有者用户可以在预取阶段就完成Post过滤,进一步降低数据库压力 if current_user.is_authenticated and not current_user.is_superuser: return Chapter.objects.prefetch_related( Prefetch('post_set', queryset=Post.objects.filter(is_archived=False)) ).all() # 所有者/管理员预取全部关联Post return Chapter.objects.prefetch_related('post_set').all()
内容的提问来源于stack exchange,提问作者Dmytro
相关产品推荐
相关产品推荐

