将变量从中间件传递到模板
Pass variable from middleware to templates
我是 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')
您可以定义一个 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', { })
我是 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')
您可以定义一个 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', { })