Django DRF详情接口调用get_language返回默认语言问题排查
可能的问题原因
- 类属性queryset的加载时机错误:这是最可能的原因。
ModelViewSet的类属性queryset = Blog.l_objects.all()是在项目启动、类加载阶段就完成计算的,此时还没有收到用户请求,get_language()拿到的是全局默认语言。而list、childs接口都是在请求处理方法内动态调用Blog.l_objects生成查询集,是请求到达后才执行,能正确拿到当前用户激活的语言。默认的retrieve(即blog/{id}详情接口)会直接复用类属性提前生成的旧查询集,所以过滤条件用的是默认语言。 - 详情序列化器的逻辑问题:检查
BlogDetailSerializer内部是否有直接调用Blog.objects查询数据、或者在序列化器类属性定义阶段就调用了get_language()的逻辑,这两种情况都会导致拿到的是默认语言。 - 详情接口缓存问题:如果给
retrieve接口单独配置了缓存,缓存中保存的是早期默认语言的返回结果,也会出现该问题。 - 语言激活逻辑遗漏:检查Django配置中
LocaleMiddleware的顺序是否正确(需放在SessionMiddleware、CommonMiddleware之后,其他业务中间件之前),虽然其余接口正常,但如果有针对详情接口的特殊路由规则跳过了语言激活逻辑也会导致异常。
建议修复方案
优先替换类属性的静态queryset,改为重写get_queryset方法动态生成查询集:
class BlogViewSet(ModelViewSet): serializer_class = BlogSerilizer detail_serializer_class = BlogDetailSerializer def get_queryset(self): return Blog.l_objects.all() # 其余原有逻辑保持不变 def get_serializer_class(self): if self.action == "retrieve": return self.detail_serializer_class return super().get_serializer_class() def list(self, request, *args, **kwargs): queryset = self.get_queryset().filter(parent=None) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) @action(detail=True, methods=["get"]) def childs(self, request, id): child_blogs = self.get_queryset().filter(parent_id=id) serializer = self.get_serializer(child_blogs, many=True) return Response(serializer.data)
内容的提问来源于stack exchange,提问作者D_P
相关产品推荐
相关产品推荐

