好吧,这可能是一个非常愚蠢的问题,但我是Python / Django的新手,所以我还不能真正地围绕它的范围概念。现在我正在写一个middleware类来处理一些东西,我想设置我的视图和模板可以访问的“全局”变量。这样做的“正确”方法是什么?我考虑做过这样的事情:
from django.conf import settings
class BeforeFilter(object):
def process_request(self, request):
settings.my_var = 'Hello World'
return None
from django.conf import settings
from django.http import HttpResponse
def myview(request):
return HttpResponse(settings.my_var)
虽然这有效,但我不确定这是“Django方式”还是“Python方式”。
所以,我的问题是:
这是正确的方法吗?
2.如果它是正确的方法,添加可以在中间件的实际模板中使用的变量的正确方法是什么?假设我想评估一些内容,并且我想在中间件中将变量headername
设置为“我的站点名称”,并且我希望能够在所有模板中执行{{ headername }}
。按照我现在的方式进行操作我必须将headername
添加到每个视图中的上下文中。反正有没有绕过这个?我正在思考CakePHP $this->set('headername','My Site Name');
的问题
3.我使用中间件类作为CakePHP的beforeFilter
的等价物,它在每个视图(或CakePHP中的控制器)被调用之前运行。这是正确的做法吗?
4.完全无关,但这是一个小问题,将变量内容打印到浏览器ala print_r
的好方法是什么?说我想看到传递到视图中的request
内的所有内容? pprint
是答案吗?
答案 0 :(得分:19)
这不是最好的方法。您可以在请求而不是设置上设置my_var。设置是全局的,适用于整个站点。您不希望为每个请求修改它。多个请求同时更新/读取变量可能会出现并发问题。
要在模板中访问request.my_var,您可以执行 {{request.my_var}} 。要访问模板中的请求变量,您必须将 django.core.context_processors.request 添加到 TEMPLATE_CONTEXT_PROCESSORS 设置。
是。描述请求中间件的其他术语将是请求预处理器/过滤器/拦截器。
此外,如果您想在模板中使用标题的常用站点名称,您可能需要查看Django站点应用程序,该应用程序提供了一个站点名称变量供您使用。
答案 1 :(得分:12)
这就是我们的工作。我们使用像这样的上下文处理器......
def context_myApp_settings(request):
"""Insert some additional information into the template context
from the settings.
Specifically, the LOGOUT_URL, MEDIA_URL and BADGES settings.
"""
from django.conf import settings
additions = {
'MEDIA_URL': settings.MEDIA_URL,
'LOGOUT_URL': settings.LOGOUT_URL,
'BADGES': settings.BADGES,
'DJANGO_ROOT': request.META['SCRIPT_NAME'],
}
return additions
此处激活此设置。
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
"myapp. context_myApp_settings",
)
这在呈现的每个模板的上下文中提供“全局”信息。这是标准的Django解决方案。有关上下文处理器的更多信息,请参阅http://docs.djangoproject.com/en/dev/ref/templates/api/#ref-templates-api。
“将变量内容打印到浏览器ala print_r的好方法是什么?”
在视图中?您可以为要呈现的模板提供pprint.pformat
字符串以进行调试。
在日志中?您必须使用Python的logging
模块并将内容发送到单独的日志文件。使用简单的print语句将内容写入日志对于所有Django实现都不能很好地保持一致(例如,mod_python会丢失所有stdout和stderr的东西。)
答案 2 :(得分:4)
1)如果您修改“设置”,即使跨请求,这也是真正的全局。换句话说,如果您需要每个请求都有自己的值,并发请求将相互踩踏。修改请求对象本身更安全,这是一些常见的Django中间件(例如django.contrib.auth.middleware.AuthenticationMiddleware在请求对象上添加对'user'的引用)
2)(编辑2)参见#4,在每个模板中获取一组通用变量可能更适合自定义上下文处理器
3)我不熟悉CakePHP,但添加process_request中间件绝对是预处理每个请求的良好Django方式。
4)看一下template context processors的文档。如果使用RequestContext,每个模板都会有一个名为“request”的上下文变量,您可以将其转储到模板中。您也可以使用调试上下文处理器并执行类似这样的操作,以便仅在settings.DEBUG = True时转储:
{% if debug %}
<!-- {{ request.REQUEST }} -->
{% endif %}
这适用于GET和POST,但如果您只需要一个或另一个,则可以相应地进行修改。
修改强>
另外,我只是仔细看看你的views.py。不确定我只是在响应中返回变量,完全理解你要做的事情。如果你真的有这个用例,你可能也想设置像这样的mimetype:
return HttpResponse (..., mimetype='text/plain')
这只是要明确表示您没有返回HTML,XML或其他一些结构化内容类型。
编辑2
刚看到问题已经更新了一个新的子问题,重新编号的答案