Skip to main content
 首页 » 编程设计

python之Django REST Framework 如何将上下文添加到 ViewSet

2025年05月04日36虾米哥

ViewSets 做我想做的一切,但我发现如果我想将额外的上下文传递给模板(使用 TemplateHTMLRenderer),那么我将不得不获得提供响应的函数..(如 list(),创建()等)

我能看到的唯一方法是在我的 ViewSet 中完全重新定义它们,但似乎应该有一种简单的方法可以向模板添加一些上下文,而不必重新定义一整套方法...

class LanguageViewSet(viewsets.ModelViewSet): 
    """Viewset for Language objects, use the proper HTTP methods to modify them""" 
    # TODO: add permissions for this view? 
    queryset = Language.objects.all() 
    serializer_class = LanguageSerializer 
    filter_backends = (filters.DjangoFilterBackend, ) 
    filter_fields = ('name', 'active') 

现在我的代码看起来像这样,但我想为响应添加不同的上下文,并且我试图避免为这么小的更改重新定义整个方法。像这样……

class LanguageViewSet(viewsets.ModelViewSet): 
    """Viewset for Language objects, use the proper HTTP methods to modify them""" 
    # TODO: add permissions for this view? 
    queryset = Language.objects.all() 
    serializer_class = LanguageSerializer 
    filter_backends = (filters.DjangoFilterBackend, ) 
    filter_fields = ('name', 'active') 
 
    def list(self, **kwargs): 
        """Redefinition of list""" 
 
        ..blah blah everything that list does 
        return Response({"foo": "bar"}, template_name="index.html") 

请您参考如下方法:

我在 Django Rest Framework (DRF) 3.x 中遇到了同样的问题,但解决方法略有不同。我相信没有必要在 TemplateHTMLRenderer 类上覆盖相对复杂的渲染方法,而只需覆盖更简单的方法 get_template_context (或:resolve_context在早期版本的 DRF 中)。

过程如下:

  1. 覆盖 ViewSet 上的 get_renderer_context 方法(如前所述):

    def get_renderer_context(self): 
        context = super().get_renderer_context() 
        context['foo'] = 'bar' 
        return context 
    
  2. 子类 TemplateHTMLRenderer,但只覆盖 get_template_context 方法而不是整个渲染方法(渲染调用 self.get_template_context 来检索传递给模板的最终上下文):

    class ModifiedTemplateHTMLRenderer(TemplateHTMLRenderer): 
     
        def get_template_context(self, data, renderer_context): 
     
        """ 
        Override of TemplateHTMLRenderer class method to display 
        extra context in the template, which is otherwise omitted. 
        """ 
     
        response = renderer_context['response'] 
        if response.exception: 
            data['status_code'] = response.status_code 
            return data 
        else: 
            context = data 
     
            # pop keys which we do not need in the template 
            keys_to_delete = ['request', 'response', 'args', 'kwargs'] 
            for item in keys_to_delete: 
                renderer_context.pop(item) 
     
            for key, value in renderer_context.items(): 
                if key not in context: 
                    context[key] = value 
            return context 
    

{{ foo }} 现在可用作模板变量 - 与 get_renderer_context 中添加的所有其他变量一样。