Django:为所有(class-based)视图提供全局方法?
Django: provide global method to all (class-based) views?
我需要一个按钮,它包含在我的 Django 应用程序的每个页面的页眉中,以触发一些全局方法,以切换会话中的“mode
”设置。有两种模式:'preview'和'publish'。
我想出了一个解决方案:在每个(class-based)视图中复制一个 post()
方法,以处理模式更改。这看起来很难干。
另一种方法是从单个 superclass 继承我所有的 CBV,或者使用 mixin。我想这是可能的。
也许是更好的解决方案:我设置了一个 context_processor
来处理将模式全局发布到我的模板。这很好用。我还设置了一个 middleware
class 和 process_request
,理论上可以在全球范围内处理 POST
请求。但是如何从我的模板中调用此 process_request
方法?
我目前的尝试如下。如何切换模板中的 "preview" 和 "publish" 按钮,并调用中间件?
template.html
:
<html>
<head></head>
<body>
<header>
<form method="post">
{% csrf_token %}
<!-- button toggle -->
{% if mode == 'preview' %}
<button name="mode" value="publish">Publish</button>
{% else %}
<button name="mode" value="preview">Preview</button>
{% endif %}
</form>
</header>
</body>
</html>
middleware.py
:
class MyMiddleware(object):
def process_request(self, request):
update_mode(request)
def update_mode(request, new_mode=None): # how do I call this from template?
modes = [
'preview',
'publish'
]
# ensure default
if not request.session.get('mode', None):
request.session['mode'] = 'preview'
# set new mode
if new_mode and new_mode in modes:
request.session['mode'] = new_mode
context_processor.py
:
def template_mode(request):
context = {
'mode': request.session['mode']
}
return context
您没有 "call" 中间件:这根本不是它的工作原理。每个请求都会调用中间件,因此在您的情况下 update_mode 函数将始终 运行.
更好的解决方案是将包含 post 按钮的表单转换为新的 URL,这会调用视图来更新模式。您可以添加一个包含当前 URL 的隐藏字段 - 您可以从 request.path
获得 - 更新模式视图可以在完成工作后重定向回 URL。
我不会那样做 - 为表单制作一个模板标签怎么样?
在你的templatetags.py中:
def set_session_mode_form():
return {'session_form': SessionForm()}
register.inclusion)tag("<path-to-your-template>",set_session_mode_form)
然后您的会话表单会发送到一个视图,该视图会更新您想要的会话变量。
要使用它,只需在您的页面上加载标签并使用 {% include %}。这样,它很容易添加到任何页面,并保持干燥。
我需要一个按钮,它包含在我的 Django 应用程序的每个页面的页眉中,以触发一些全局方法,以切换会话中的“mode
”设置。有两种模式:'preview'和'publish'。
我想出了一个解决方案:在每个(class-based)视图中复制一个 post()
方法,以处理模式更改。这看起来很难干。
另一种方法是从单个 superclass 继承我所有的 CBV,或者使用 mixin。我想这是可能的。
也许是更好的解决方案:我设置了一个 context_processor
来处理将模式全局发布到我的模板。这很好用。我还设置了一个 middleware
class 和 process_request
,理论上可以在全球范围内处理 POST
请求。但是如何从我的模板中调用此 process_request
方法?
我目前的尝试如下。如何切换模板中的 "preview" 和 "publish" 按钮,并调用中间件?
template.html
:
<html>
<head></head>
<body>
<header>
<form method="post">
{% csrf_token %}
<!-- button toggle -->
{% if mode == 'preview' %}
<button name="mode" value="publish">Publish</button>
{% else %}
<button name="mode" value="preview">Preview</button>
{% endif %}
</form>
</header>
</body>
</html>
middleware.py
:
class MyMiddleware(object):
def process_request(self, request):
update_mode(request)
def update_mode(request, new_mode=None): # how do I call this from template?
modes = [
'preview',
'publish'
]
# ensure default
if not request.session.get('mode', None):
request.session['mode'] = 'preview'
# set new mode
if new_mode and new_mode in modes:
request.session['mode'] = new_mode
context_processor.py
:
def template_mode(request):
context = {
'mode': request.session['mode']
}
return context
您没有 "call" 中间件:这根本不是它的工作原理。每个请求都会调用中间件,因此在您的情况下 update_mode 函数将始终 运行.
更好的解决方案是将包含 post 按钮的表单转换为新的 URL,这会调用视图来更新模式。您可以添加一个包含当前 URL 的隐藏字段 - 您可以从 request.path
获得 - 更新模式视图可以在完成工作后重定向回 URL。
我不会那样做 - 为表单制作一个模板标签怎么样?
在你的templatetags.py中:
def set_session_mode_form():
return {'session_form': SessionForm()}
register.inclusion)tag("<path-to-your-template>",set_session_mode_form)
然后您的会话表单会发送到一个视图,该视图会更新您想要的会话变量。 要使用它,只需在您的页面上加载标签并使用 {% include %}。这样,它很容易添加到任何页面,并保持干燥。