django:为什么RequestContext设置为context_instance?

时间:2009-08-01 04:00:03

标签: django django-templates

似乎大多数文档建议:

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)

5 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

关于“样板代码”,这已经内置于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..})

答案 2 :(得分:2)

现在已经在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 dict中,使其与render_to_response的大多数用法不兼容(切换时通常需要进行模板重构)从render_to_responsedirect_to_template)。具有讽刺意味的是生活在django.shortcuts中的render_to_response,并不是一个经过深思熟虑的捷径。它应该将关键字参数转换为模板参数,并且笨拙的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)

答案 3 :(得分:2)

我刚刚找到了这个解决方案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

答案 4 :(得分:0)

除了“锅炉板”代码,您还可以渲染到urls.py

中的模板

例如:

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