【问题标题】:Django, exclude a context processor in a viewDjango,在视图中排除上下文处理器
【发布时间】:2012-03-31 23:12:56
【问题描述】:

我有一个带有菜单的网站。要生成菜单,我需要在数据库中进行一些查询。所以我创建了一个上下文处理器来在我的所有视图中执行此操作。

我的一些观点实际上是形式。当我的用户单击某些按钮时,我使用 ajax 获取它们并使用 jquery ui 对话框显示它们。

对于那些相当复杂的表单,我无法删除所有上下文处理器,我尤其需要 auth、static 和 il8n 上下文处理器。 但我不想在数据库中进行基于菜单的查询来显示这些表单。

有没有办法在视图中排除上下文处理器? 我试图在视图中的“request.session”中放置一个变量,然后将其删除并在我的上下文处理器中返回一个空字典。但这很糟糕,并且可能存在并发问题。 我还可以在上下文处理器中解析“请求”中的 url 并返回一个空字典,但这听起来又像是一个 hack。

有什么想法或建议吗? 谢谢,

【问题讨论】:

  • 参见this question,几乎完全相同。
  • 目标相似,但惰性解决方案在我的情况下不起作用,菜单非常繁重,大多数查询实际上在我的上下文处理器期间访问数据库。特别是因为我使用的是 1.3 所以没有 prefect_related 并且我有几个多对多的关系要查询。
  • 我不明白你对惰性对象的问题。在被访问之前,它实际上甚至不会调用您的函数;如果您愿意,可以查看in the source。
  • 您说的完全正确,您介意将其发布为答案以便我验证吗?在我看来,这显然是最好的方法。

标签: python django django-views


【解决方案1】:

这就是 Django 的惰性对象的用途。与其在上下文处理器中计算实际内容,不如提供一个带有关联函数的惰性对象;当某些东西实际上试图使用该对象时,例如在模板中,然后它调用该函数。 This answer 给出了相同问题的示例。

如果您多次使用该变量,请注意记忆;一些选项将重新调用该函数,而一些选项将保存结果。您可以查看the source 来确定。我认为SimpleLazyObject(如上面的答案)可以满足您的需求,但我最近还没有使用它来确定。

(根据要求回答......)

【讨论】:

  • 我尝试了一个执行 User.objects.get 的函数,然后在模板中多次包含结果,我只能看到一个带有调试工具栏的数据库请求。我认为它的工作原理与您告诉我的默认选项完全一样。
【解决方案2】:

您可以在django.template.context 中继承RequestContext 并重新定义其__init__ 方法。然后,您可以在这些特定视图中使用此修改后的RequestContext。 RequestContext 的 __init__ 目前看起来像这样:

def __init__(self, request, dict=None, processor=None, current_app=None, use_l10n=None): 上下文.__init__(self, dict, current_app=current_app, use_l10n=use_l10n) 如果处理器是无: 处理器 = () 别的: 处理器 = 元组(处理器) 对于 get_standard_processors() + 处理器中的处理器: self.update(处理器(请求))

在这里,get_standard_processors() 返回设置中定义的上下文处理器。在调用上下文处理器(上述代码的最后一行)之前,您可以添加一个检查以确定需要使用哪些处理器以及需要跳过哪些处理器。

【讨论】:

  • 谢谢,我一定会试试的!我不喜欢重新定义标准东西的行为,以避免新版本出现任何问题,但这看起来很无害。
【解决方案3】:

重新设计您的应用程序可能会更容易,这样一些视图会进行此查询,而其他视图则不会。您可以通过编写一个“基于类的视图”来进行此特定数据库查询并将其添加到上下文中,然后在您需要新视图进行额外查询时继承它,从而避免这种导致大量重复的情况。我提倡这种方法,而不是全局上下文处理器。

This example 展示了如何向默认模板上下文添加内容。

【讨论】:

  • 谢谢!我当然想到了那个解决方案,但是因为我必须修复 100 个视图而变得懒惰。既然别人这么说,其实听上去还挺合乎逻辑的。如果我不成功,我会先尝试 Simeon 解决方案,然后使用您的解决方案。
【解决方案4】:

使用各种模板引擎很容易实现。

1。在您的项目设置中定义替代(轻型)模板引擎

TEMPLATES = [
    # The default engine - a heavy one with a lot of context processors
    {
        'NAME': 'default',
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.i18n',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.template.context_processors.static',

                'some_app_1.context_processors.very_heavy_cp_1',
                'some_app_2.context_processors.very_heavy_cp_2',
                'some_app_3.context_processors.very_heavy_cp_3',
            ],
            'debug': True,
        },
    },
    # Light engine - only very necessary things go here
    {
        'NAME': 'light',
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.i18n',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.template.context_processors.static',
            ],
            'debug': True,
        },
    },
]

2。如何在视图中使用光引擎

some_app_1.views.py

from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic import View, TemplateView

示例灯光视图:

class TestLightView(View):
    """Test light view."""

    template_name = 'some_app_1/test_light_view.html'

    def get(self, request):
        context = {}
        response = render_to_response(
            self.template_name,
            context,
            context_instance=RequestContext(request),
            using='light'  # Note, that we use `light` engine here
        )
        return response

普通(重)视图示例:

class TestNormalView(View):
    """Test normal view."""

    template_name = 'some_app_1/test_normal_view.html'

    def get(self, request):
        context = {}
        response = render_to_response(
            self.template_name,
            context,
            context_instance=RequestContext(request),
            using='default'  # Note, that we use `default` engine here
        )
        return response

如果您使用TemplateView,请定义template_engine 属性。

示例灯光视图:

class TestTemplateLightView(TemplateView):
    """Test template light view"""

    template_engine = 'light'  # Note, that we use `light` engine here

    # Your code goes here

普通(重)视图示例:

class TestTemplateNormalView(TemplateView):
    """Test template normal view."""

    template_engine = 'default'  # Note, that we use `default` engine here

    # Your code goes here

【讨论】:

    猜你喜欢
    • 2018-02-04
    • 2011-10-01
    • 2012-06-05
    • 2016-07-01
    • 1970-01-01
    • 2013-02-22
    • 2015-11-27
    • 1970-01-01
    • 2011-01-15
    相关资源
    最近更新 更多