如何在Django中向所有模板传递变量?

10

我正在尝试将变量(浏览器变量)传递给我应用程序中的所有模板。有什么建议可以让它正常工作吗?

视图:

def browser(request):
    primary_cat_list = Categories.objects.order_by("category")
    subcat_list = SubCategories.objects.order_by("sub_category")
    product = Productbackup.objects.order_by("website")
    browser =  list(chain(primary_cat_list, subcat_list, product))
    return render_to_response('reserve/templates/base.html', locals(), context_instance=RequestContext(request))

模板:

{% for prod in browser %} {{ prod }}, {% endfor %}

我不确定这是否与此有关,但是你的函数名为browser,同时你还将其赋值给一个名为browser的变量,这很奇怪。我在Python shell中进行了一些实验,似乎并不是问题所在,但你可能需要更改它以使其更清晰易懂。 - Brian Neal
还要确保你的列表不为空。尝试使用调试器或在视图中打印该值。 - Brian Neal
你是真的想知道如何让变量在所有模板中显示,还是为什么在这种特定情况下“browser”变量不起作用? - Brian Neal
@BrianNeal 我最初想知道为什么浏览器变量没有传递到base.html。这将有效地允许我在所有模板中使用该变量,这确实是我想做的事情。 - sharataka
3个回答

14

你,我的朋友,正在寻找上下文处理器(Context Processors)

根据比我敏捷和博学的技术作家撰写的一篇博客文章

什么是模板上下文处理器?

Django的上下文处理器是一种允许您向模板提供数据和回调函数的工具。

您可以通过以下两种方式之一实现:

  • 在单个请求的基础上:通过将自定义的Context值传递给您的render_to_response()调用
  • 全局性地:通过创建一个接受HttpRequest对象作为输入并返回有效负载或回调函数的上下文处理器方法,然后在settings.py中注册上下文处理器,并提供内置的RequestContext属性而不是您自己的属性来调用render_to_response()(当然,您也可以在单个请求的基础上扩展RequestContext以添加更多数据)。

如果您认为将数据传递给模板的这种方法听起来荒谬而晦涩,您并不孤单。在这样一个简单的操作中涉及了如此复杂的过程是不合理且适得其反的,但每个系统都有其缺点。

官方文档在这里:

https://docs.djangoproject.com/en/dev/ref/templates/api/

所以,我已经使用Django编程一段时间了,而我真正喜欢用它解决问题的原因之一是因为它在复杂性上几乎像拜占庭式迷宫,但并不会显得霸道。它拥有许多看似无用的小玩意儿;每当你需要时,这些小玩意儿非常实用,并且如果不需要,它们也不会碍事。

这对你来说的结果是:上下文处理器就是这些的一个很好的例子。是的。


那不是OP所问的吗?就个人而言,我倾向于同意过度设计的问题,因为我通常不会这样工作。但我也不能确定哪种方式更好,所以最好让它成为程序员的冒险,其中的教育经验远远超过我所能做出的任何评论。无论如何,这就是为什么我在结尾处添加了¶,因为Q听起来像是一个正在探索框架而不是解决特定技术问题的人。 - fish2000

4

目前你正在将locals()作为变量作用域传递,其中应该包括browser,但我觉得使用locals()非常丑陋。

个人而言,我更喜欢像这样的模式:

def browser(request):
    context = RequestContext(request)

    primary_cat_list = Categories.objects.order_by("category")
    subcat_list = SubCategories.objects.order_by("sub_category")
    product = Productbackup.objects.order_by("website")
    browser =  list(chain(primary_cat_list, subcat_list, product))

    context['browser'] = browser

    return render_to_response('reserve/templates/base.html', context_instance=context)

这似乎不起作用...base.html仍然没有显示任何内容。 - sharataka
1
@sharataka:如果是这种情况,也许列表就是空的?如果你像这样做会怎么样:browser = ['spam', 'eggs'] - Wolph

4

我可以给你展示一个正常工作的代码示例,这里是名为context_processors.py的文件:

context_processors.py

def base(request):
    user = request.user

#======================
#Login form
#=====================

# here is the code for login user or check if he is logged in already

return  {
        'user': user,
        }

这是我的base.html的一部分(我在所有页面中使用的模板)。

base.html

{% if user.username %}
                    <h3>
                        Welcome {{ user.username }}
                    </h3>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接