将变量从中间件传递到模板

Pass variable from middleware to templates

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

我创建了 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 函数并将其添加到 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}} 将 return 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',)

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

希望这对您有所帮助。

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

在您的应用程序上创建文件 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',
)

您可以在任何模板中使用 'variable':

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

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

在我看来,如果您确实需要一个随处可用的通用变量,这会使中间件优于上下文处理器。简而言之,根据文档:https://docs.djangoproject.com/en/2.2/topics/http/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', { })