【问题标题】:Pass variable from middleware to templates将变量从中间件传递给模板
【发布时间】:2015-03-20 04:49:08
【问题描述】:

我是 Django 初学者。到目前为止,我学习了从 viewtemplate 的传递变量。但现在我需要将变量传递给我的主布局。我可以在每个页面的定义中传递它。但它的重复太多了。所以我开始学习中间件。

我创建了 middlewares.py 并将其包含在设置中。在 middlewares.py 文件中,如何将变量传递给我的主布局?

以下是我目前的 middlewares.py 内容,我尝试了很多方法并把它们注释掉,因为不起作用。

from django.db import connections
from django.shortcuts import render, redirect

class NotificationsMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):

        request.context_data['notification_count'] = 2
        response = view_func(request, *view_args, **view_kwargs)

        return response

    # def process_request(self, request):
    #     request.notification_count = 2
    #     return

    # def process_template_response(self, request, response):
    #     # response.context['notification_count'] = 2
    #     response.context_data['notification_count'] = 2
    #     # return response
    #     return render(request, 'main/locations.html')

【问题讨论】:

  • 我不明白为什么您接受了在context processor 中提供解决方案的答案,您在middleware 中专门询问了如何做到这一点
  • 就像我说的那样,我是初学者 :)
  • 是的,我明白了,不用担心。哈哈,这只是一个完美的帖子标题,可以解决我最近的问题。我通过文档弄清楚了,但我没想到上下文处理器会成为这里的主要解决方案。

标签: django variables middleware


【解决方案1】:

您可以创建一个模板上下文处理器,首先使用一个方法创建一个 python 文件,该方法返回一个包含您需要的信息的字典,然后使用您的示例在项目设置中添加到该文件的路由:

在您的应用上创建一个文件context_processors.py

 from myapp.models import MyModel

 def my_context(request):
    context_data = dict()
    context_data['notification_count'] = MyModel.objects.all().count()
    return context_data

在你的 settings.py

中添加上下文处理器
TEMPLATE_CONTEXT_PROCESSORS = (
    #  ...
    'myapp.context_proccessors.my_context',
)

您可以在任何模板中使用“变量”:

<p>Count: {{ notification_count }}</p>

【讨论】:

  • 它并不总是返回 2。我需要从数据库中读取它,然后将行数作为数字返回。也迟早要归队。模板上下文能做到吗?
  • 您可以在上下文处理器文件中导入模型并将数字 2 更改为任何内容;)
  • 由于 Django 1.8 TEMPLATE_CONTEXT_PROCESSORS 已被弃用。实际将 'myapp.context_proccessors.my_contex' 添加到 DjangoTemplates 后端的 OPTIONS 中的 'context_processors' 选项中。请参阅文档:docs.djangoproject.com/en/1.8/ref/settings/…
【解决方案2】:

您可以定义一个context processor 函数并将其添加到settings.py 中定义的TEMPLATE_CONTEXT_PROCESSORS 列表中。

假设您有一个名为 project/context_processors.py 的文件,您可以创建一个基本上将您的值传递给所有模板的函数。

def notification_count(request):
    return {'notification_count': 2}

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    'context_proccessors.notification_count',
)

在模板中调用 {{notification_count}} 将返回 2。

您可以查看官方documentation 了解有关上下文处理器的更多信息。


如您所说,第二种方法是使用中间件。但是,我认为这有点矫枉过正,因为您可以通过中间件进行更复杂的计算。

middlewares.py

class NotificationsMiddleware(object):
    def process_template_response(self, request, response):
        if not ('notification_count' in response.context_data):
            response.context_data['notification_count'] = 2
        return response

请注意,您应该将中间件添加到设置文件中定义的MIDDLEWARE_CLASSES 列表中。

MIDDLEWARE_CLASSES += ('middlewares.NotificationsMiddleware',)

请参阅中间件documentation,了解有关如何在 Django 框架中更改请求-响应周期的更多信息。

希望这会有所帮助。

【讨论】:

  • 1.我遵循了您的 context_processor 方法。但是有错误:将 'django.contrib.auth.context_processors.auth' 放入您的 TEMPLATE_CONTEXT_PROCESSORS 设置中,以便使用管理应用程序。
  • 如果您的设置中已经定义了TEMPLATE_CONTEXT_PROCESSORS 列表,请将您的上下文处理器添加到其中,而不是从django.conf.global_settings 导入的那个。也就是说,删除这行from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS,然后再试一次。我已经更新了我的答案。
  • 按照 OP 的要求展示了一个带有中间件的示例,做得很好。
【解决方案3】:

中间件允许你将数据绑定到request,这意味着如果你使用中间件而不是上下文处理器,你可以在模板和视图中访问这个通用变量数据,或者实际上在任何地方request 对象用于整个代码库。

在我看来,如果您确实需要一个随处可用的通用变量,这使得中间件优于上下文处理器。简而言之,根据文档:https://docs.djangoproject.com/en/2.2/topics/http/middleware/ Middleware 在每次视图调用时都会被调用。

这是一个使用您的代码和中间件的简单示例

class NotificationsMiddleware(object):

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):

        # I am showing this as a standard var not a dict as you originally had it, 
        # for simplicity, this is now a request attribute called notification_count
        request.notification_count = 2

        response = self.get_response(request)

        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        # You don't need this method for the middleware to work anymore
        # with Django as the __call__ method covers it, so you can delete it.
        pass

现在将自定义中间件传递给如下设置:

MIDDLEWARE = [
    ...
    # custom middleware
    '[YOUR-PATH].NotificationsMiddleware'
]

现在您可以像这样在任何模板中调用该变量:

{{ request.notification_count }}

或者在任何视图中,像这样:

def index(request):

    print(' Notification Count =', request.notification_count)
    ...
    return render(request, 'index.html', { })

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    • 2023-01-11
    • 2017-11-11
    • 2019-04-03
    • 2011-05-08
    • 2015-08-24
    • 1970-01-01
    相关资源
    最近更新 更多