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

时间:2015-03-20 04:49:09

标签: django variables middleware

我是Django的首发。到目前为止,我学习了从 view template 的传递变量。但现在我需要将变量传递给我的主要布局。我可以在每个页面的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')

3 个答案:

答案 0 :(得分:5)

您可以创建一个模板上下文处理器,首先使用一个方法创建一个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>

答案 1 :(得分:3)

您可以定义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',)

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

希望这有帮助。

答案 2 :(得分:0)

中间件允许您将数据绑定到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', { })