为啥我必须在所有回复中传递 RequestContext ?

Posted

技术标签:

【中文标题】为啥我必须在所有回复中传递 RequestContext ?【英文标题】:Why on earth do I have to pass RequestContext in all of my responses?为什么我必须在所有回复中传递 RequestContext ? 【发布时间】:2010-11-06 08:13:45 【问题描述】:

我想在导航菜单中突出显示当前页面。显然,当您在他们的页面上时,我需要为菜单链接提供一个类似于“活动”的类。这是一个经典问题,我见过很多解决方案proposed。我的问题是我讨厌所有这些,并且认为它们都不是很干燥。例如:

@register.simple_tag
def active(request, pattern):
    import re
    if re.search(pattern, request.path):
        return 'active'
    return ''

----

% load tags %
<div id="navigation">
    <a class="% active request "^/about/" %" href="/about/">About</a>
    <a class="% active request "^/contact/" %" href="/contact/">Contact</a>
    <a class="% active request "^/services/" %" href="/services/">Services</a>
</div>

如果您当前在此页面上,该标签将获取您当前的请求和一个 url 表达式并返回“活动”。或者,这可以使用命名视图而不是 url 来完成,但原理是相同的。

我的主要问题是我的导航将在 99% 的视图上调用,然而,为了获取当前请求变量,我仍然需要将 RequestContext 解析为模板,如下所示:

def contact(request):
    # snip ...
    return render_to_response(
                'contact.html',
                 'myvar' : myvar ,
                context_instance=RequestContext(request))

为什么我需要将这个 context_instance 行添加到我的每一个视图中,而其中可能除了其中一个之外需要请求变量以获取当前 url/view 以突出显示活动关联?这似乎非常潮湿,特别是对于必须在绝大多数 django 站点中的功能。我希望默认情况下包含该请求,并且可以选择禁止它。我找不到在中间件中执行此操作的方法,因为在视图返回模板后,我无法在模板呈现之前拦截它。

有什么建议吗?

【问题讨论】:

【参考方案1】:

您的意图是有道理的,您大部分时间都需要RequestContext,而且出于性能原因,很少可以安全地省略它。解决方法很简单,不用render_to_response使用direct_to_template快捷方式:

from django.views.generic.simple import direct_to_template

def contact(request):
    # snip ...
    return direct_to_template(request, 'contact.html',  'myvar' : myvar )

... 或来自django-annoying 的render_to 装饰器:

from annoying.decorators import render_to

@render_to('template.html')
def foo(request):          
    bar = Bar.object.all()  
    return 'bar': bar     

【讨论】:

@render_to 装饰器很棒!谢谢! +1 推荐@render_to!请注意,django-annoying 由于不活动而被接管和移动 4 年后,Django 1.5 删除了“direct_to_template”。现在推荐的方法是什么,而不使用 django-annoying【参考方案2】:

您不一定要对导航标记做任何事情来为当前导航标记提供不同的样式 - 使用 CSS 可以通过声明性方式做到这一点。

在此处查看我的答案:Django: Is there a better way to bold the current page link 示例。

【讨论】:

使用正文 id 命名您的页面是个好主意,但正文标记以及导航位于基本模板中。我可以阻止它并将 % block body_id %my-page% endblock % 添加到每个扩展模板中,但同样,DRY 在哪里?有什么办法可以自动化吗?我想将命名视图用作主体 id 或将其 slugify 或其他东西,而不是必须显式命名它并且必须为每个视图维护两个单独的“名称”:一个用于视图本身,一个用于 css id . 我的 Django-fu 生锈了,但与其更改每个扩展模板,不如从 contact() 和 family 中传入 CSS 名称: def contact(request): render_to_response('contact.html' , 'cssClass': 'contact-page', 'myvar': myvar, ...) ?仍然不是完全干燥,但还不错。【参考方案3】:

为了将来参考,可以使用django-tabs 来做 OP 想做的事情。

【讨论】:

以上是关于为啥我必须在所有回复中传递 RequestContext ?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在这种情况下我必须将指针传递给指针

为啥在使用单指针传递给函数时必须对二维数组进行类型转换?

为啥传递给runnable的变量必须是final的?

为啥数据不从视图传递到控制器

为啥我必须将道具传递给构造函数和超级[重复]

为啥我从 google drive rest api 得到服务器回复被禁止?