【问题标题】:What are Django context processors?什么是 Django 上下文处理器?
【发布时间】:2018-05-10 07:04:54
【问题描述】:

我正在为这些概念而苦苦挣扎。比如我有这个视图功能

def post_detail(request, year, month, day, post):
    post = get_object_or_404(Post, slug=post,status='published',p__year=year,p__month=month,p__day=day,status='published',)
    return render(request,'blog/post/detail.html',{'post': post})

据我了解,函数将请求对象作为参数,模板路径和变量来呈现给定模板。到现在为止还可以。但是现在出现了模板上下文处理器和幕后的魔力。来自djangoproject

TEMPLATE_CONTEXT_PROCESSORS 设置是一个可调用元组—— 称为上下文处理器——将请求对象作为它们的 参数并返回要合并到 上下文

他们实际上在做什么?他们会在模板中公开数据,对输入数据有什么限制吗?

【问题讨论】:

  • 文档中有一个示例,其中还列出了您可以查看的所有默认上下文处理器。目前尚不清楚您在问什么-它们是什么(在您发布的报价中已对此进行了回答),它们在做什么(请参阅它们的各种实现)或是否存在限制(您的意思是什么)?跨度>
  • @jonrsharpe 例如请求对象可以是任何 Python 对象?我遇到过,如果 request.method == 'POST'.Type(request) 没有约束?
  • 你是什么意思“任何Python对象”?请求对象将是a request object
  • HttpRequest 类的实例?
  • 但现在您似乎已将问题从上下文处理器切换到请求对象。

标签: django


【解决方案1】:

我想你在看context_processors 的工作原理,对吧?

您可以看到 django 源代码 - 它非常棒且组织良好。

这是跟踪源代码的最佳方式,但我尝试解释一下。

首先,如果您对几乎每个视图都使用 render (或者可能是 render_to_response )。 (即使在 CBV 中)。

它返回带有内容的HttpResponse - 它使用loader.render_to_string。为了便于理解,我在下面附上render_to_response

def render_to_response(template_name, context=None, content_type=None, status=None, using=None):
    """
    Returns a HttpResponse whose content is filled with the result of calling
    django.template.loader.render_to_string() with the passed arguments.
    """
    content = loader.render_to_string(template_name, context, using=using)
    return HttpResponse(content, content_type, status)

然后你可以找到loader.render_to_string 需要context。它返回template.render(context, request)

class Template(object):

    def __init__(self, template, backend):
        self.template = template
        self.backend = backend

    @property
    def origin(self):
        return self.template.origin

    def render(self, context=None, request=None):
        context = make_context(context, request, autoescape=self.backend.engine.autoescape)
        try:
            return self.template.render(context)
        except TemplateDoesNotExist as exc:
            reraise(exc, self.backend)

正如您在上面看到的,它使用make_context 定义context。在那里,django 会自动添加一些您在settings.py 中定义的上下文。

def make_context(context, request=None, **kwargs):
    """
    Create a suitable Context from a plain dict and optionally an HttpRequest.
    """
    if context is not None and not isinstance(context, dict):
        raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
    if request is None:
        context = Context(context, **kwargs)
    else:
        # The following pattern is required to ensure values from
        # context override those from template context processors.
        original_context = context
        context = RequestContext(request, **kwargs)
        if original_context:
            context.push(original_context)
    return context

它使用RequestContext 从设置中调用处理器并将其绑定到上下文。

Here,您可以查看完整的RequestContext代码。

希望对你有帮助。

【讨论】:

  • 感谢您的详细回答。我是 Django 新手。 render 方法是否默认自动进行 HTML 转义?
  • 是的。 DjangoTemplates 选项中有 autoescape 设置。它默认为 True,您可以更改为 False。试试看这里 (docs.djangoproject.com/en/dev/topics/templates/…)
【解决方案2】:

对于每个 django 视图,无论是基于函数的视图还是基于类的视图,您都将在渲染 html 时返回上下文,如您所提到的。如果您想要的只是一个简单的页面,其中包含一些数据来显示一切都很好。但是,如果您希望在每个页面上获取一些特定数据,例如假设用户详细信息或菜单等,那么很难在您编写的每个视图中插入这些数据。这就是为什么你有上下文处理器,你可以编写一个简单的类/函数,它返回一个应该与每个视图的上下文合并的字典。现在您的菜单和用户数据将无缝呈现

【讨论】:

    猜你喜欢
    • 2016-07-01
    • 1970-01-01
    • 2010-10-24
    • 2014-02-17
    • 1970-01-01
    • 2011-01-15
    • 2010-11-04
    • 1970-01-01
    • 2017-10-24
    相关资源
    最近更新 更多