【问题标题】:django: Why is RequestContext set as context_instance?django:为什么将 RequestContext 设置为 context_instance?
【发布时间】:2009-08-01 04:00:02
【问题描述】:

似乎大多数文档都推荐:

template_values = {}
template_values["foo"] = "bar"
return render_to_response(path, template_values, context_instance=RequestContext(request)

我为什么不使用:

template_values = RequestContext(request)
template_values["foo"] = "bar"
return render_to_response(path, template_values)

【问题讨论】:

    标签: django django-templates


    【解决方案1】:

    RequestContext 不继承自dict,因此不能保证实现dict 的所有方法(它不会),并且任何在dicts 上操作的函数都可能不起作用,任何一个。最后,没有理由这样做;最好将其视为一个不透明的对象,其实现可能会发生变化。使用dict 提供模板的上下文具有RequestContext 的所有优点,没有缺点。

    更新

    为了减少样板代码,我使用了以下两个实用函数。我将它们放在项目基础的 shortcuts.py 文件中。

    from django.template import RequestContext
    def render_template(request, template, data=None):
        "Wrapper around render_to_response that fills in context_instance for you."
        response = render_to_response(template, data,
                                  context_instance=RequestContext(request))
        return response
    
    def boilerplate_render(template):
        "Factory function for creating simple views that only forward to a template"
        def view(request, **kwargs):
            response = render_template(request, template, kwargs)
            return response
        return view
    

    用法:

    def my_view(request):
        # Do stuff here...
        return render_template(request, 'my_template.html', {'var1': 'value', etc..})
    
    my_view2 = boilerplate_render('my_template2.html') # Takes no context parameters
    

    【讨论】:

    • 太棒了。谢谢你。我的最后一行似乎有点冗长,并且出现在我的每一个观点的末尾。有什么建议可以避免我一直复制粘贴吗?
    【解决方案2】:

    关于“样板代码”,这已经内置在 Django 中。只需使用通用视图:

    from django.views.generic.simple import direct_to_template
    
    def my_view(request):
        # Do stuff here...
        return direct_to_template(request, 'my_template.html', {'var1': 'value', etc..})
    

    【讨论】:

      【解决方案3】:

      一段时间以来,我一直在研究 Django 样板。 Django 有(至少)三个非常相似的模板渲染函数,每个函数都有不同程度的快捷方式:

      django.shortcuts.render_to_response
      django.template.loader.render_to_string
      django.views.generic.simple.direct_to_template
      

      似乎其中至少两个(可能是 render_to_response 和 direct_to_template)可以重构为一个单一的、不那么样板的快捷方式。

      django.views.generic.simple.direct_to_template 本身就足够好,但不幸的是,将关键字参数放在 params 字典中,使其与 render_to_response 的大多数用途不兼容(从 render_to_response 切换到 @ 时,通常需要模板重构987654326@)。 render_to_response,讽刺地生活在 django.shortcuts 中,几乎不是一个经过深思熟虑的捷径。它应该将关键字参数转换为模板参数,而且那个笨拙的 context_instance 参数太长了,不能经常输入。

      我尝试了一个更有用的快捷方式。请注意使用*request_and_template_and_params 以防止模板参数名称和位置参数名称之间发生冲突。

      def render(*request_and_template_and_params, **kwargs):
          """Shortcut for rendering a template with RequestContext
      
          Takes two or three positional arguments: request, template_name, and
          optionally a mapping of template parameters. All keyword arguments,
          with the excepiton of 'mimetype' are added to the request context.
      
          Returns a HttpResponse object.
          """
          if len(request_and_template_and_params) == 2:
              request, template_name = request_and_template_and_params
              params = kwargs
          else:
              request, template_name, params = request_and_template_and_params
              params = dict(params) # copy because we mutate it
              params.update(kwargs)
          httpresponse_kwargs = {'mimetype': params.pop('mimetype', None)}
          context = RequestContext(request, params)
          return HttpResponse(loader.render_to_string(
              template_name, context_instance=context), **httpresponse_kwargs)
      

      【讨论】:

        【解决方案4】:

        我刚刚找到了这个解决方案here,我只是稍微修改了一下:

        def render_to(template_name):
            def renderer(func):
                def wrapper(request, *args, **kw):
                    output = func(request, *args, **kw)
                    if not isinstance(output, dict):
                        return output
                    return render_to_response(template_name, output,
                            context_instance=RequestContext(request))
                return wrapper
            return renderer
        
        @render_to('my_template.html')
        def my_view(request):
            # View code here...
            return some_dict
        

        【讨论】:

          【解决方案5】:

          除了“样板”代码,您可以在 urls.py 中渲染到模板

          例如:

          url(r'^about/$', direct_to_template, {'template': 'about.html',}),
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-10-28
            • 2015-08-29
            • 2011-08-11
            • 2011-05-26
            • 2014-03-20
            • 2019-04-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多