Django-让中间件与视图/模板通信

2024-10-05 10:07:37 发布

您现在位置:Python中文网/ 问答频道 /正文

好吧,这可能是一个非常愚蠢的问题,但我对Python/Django还不熟悉,所以我还不能真正理解它的范围概念。现在我正在编写一个middleware类来处理一些事情,我想设置视图和模板可以访问的“全局”变量。做这件事的“正确”方法是什么?我考虑过这样做:

中间件.py

from django.conf import settings

class BeforeFilter(object):
    def process_request(self, request):
        settings.my_var = 'Hello World'
        return None

视图.py

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');
三。我使用中间件类作为CakePHP的beforeFilter的等价物,它在调用每个视图(或CakePHP中的控制器)之前运行。这样做对吗?
四。完全不相关,但这是一个小问题,什么是将变量内容打印到浏览器alaprint_r的好方法?假设我想查看传入视图的request中的所有内容?答案是pprint吗?


Tags: 中间件django方法frompyimport视图模板
3条回答

1)如果您修改了“设置”,这将是真正的全球,即使是跨请求。换言之,如果您需要每个请求都有自己的值,那么并发请求将相互攻击。更安全的做法是修改请求对象本身,这是一些常见的Django中间件所做的(例如Django.contrib.auth.middleware.AuthenticationMiddleware在请求对象上添加对“user”的引用)

2)(编辑2)参见#4,在每个模板中获取一组公共变量可能更适合于自定义上下文处理器

3)我不熟悉CakePHP,但是添加process_请求中间件绝对是预处理每个请求的好方法。

4)查看文档中的template context processors。如果使用request context,则每个模板都有一个名为“request”的上下文变量,可以将其转储到模板中。您还可以使用调试上下文处理器并执行类似的操作,以便它仅在设置为.debug=True时转储:

{% if debug %}
  <!-- {{ request.REQUEST }} -->
{% endif %}

这对GET和POST都有效,但如果只需要其中一个,则可以相应地进行修改。

编辑

另外,我只是仔细看了看你的观点。我不确定我是否完全理解您仅仅通过返回响应中的变量来尝试执行的操作。如果您真的有这个用例,您可能还需要设置mimetype,如下所示:

return HttpResponse (..., mimetype='text/plain')

这只是为了表明您没有返回HTML、XML或其他结构化内容类型。

编辑2

刚刚看到问题更新了一个新的子问题,重新编号的答案

  1. 这不是最好的方法。你可以根据请求而不是设置设置我的变量。设置是全局的,适用于整个站点。你不想为每个请求修改它。同时更新/读取变量的多个请求可能存在并发问题。

  2. 要访问模板中的request.my_var,可以执行{{request.my_var}。若要访问模板中的请求变量,您必须将django.core.context_processors.request添加到template_context_processors设置中。

  3. 是的。描述请求中间件的其他术语是请求预处理器/过滤器/拦截器。

此外,如果您想在模板中使用一个通用的站点名称作为头部,那么您可能需要签出Django站点应用程序,该应用程序提供一个站点名称变量供您使用。

这是我们要做的。我们使用这样的上下文处理器。。。

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输出变量内容的好方法是什么?”

在视野中?您可以为模板提供一个pprint.pformat字符串,以便进行调试。

在日志里?您必须使用Python的logging模块并将内容发送到单独的日志文件。使用简单的print语句将内容写入日志并不能对所有Django实现始终如一地工作(例如,mod_python会丢失所有的stdout和stderr内容)

相关问题 更多 >

    热门问题