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 %}。这样,它很容易添加到任何页面,并保持干燥。