1

我正在开发一个不属于我的 django 项目,但正在尝试将本地 css/js 选项添加到 webapp。

在 settings_local.py 我添加了这个:

if os.path.exists('templates_local/local.css'):
    LOCAL_CSS = True
    logging.debug('LOCAL_CSS: %s' % LOCAL_CSS)
else:
    LOCAL_CSS = False
if os.path.exists('templates_local/local.js'):
    LOCAL_JS = True
    logging.debug('LOCAL_JS: %s' % LOCAL_JS)
else:
    LOCAL_JS = False

这似乎有效(见下文)。在我的主模板中,我添加了

{% if LOCAL_CSS %}
    {% compress css  %}
        {% include "../templates_local/local.css" %}
    {% endcompress  %}
{% endif %}

(该项目使用 django-compressor)。

如果存在 local.css 文件,这将按我的预期工作,但如果该文件不存在,我会收到错误消息:

渲染时捕获 TemplateDoesNotExist:../templates_local/local.css

在堆栈跟踪中,LOCAL_CSS 被列为 False。不幸的是,堆栈跟踪下降以显示 IF 没有找到文件(这是预期的),但似乎不包括 IF 的评估方式,尽管它正在执行,就好像它正在评估为 True ......但无论如何,这并不能帮助我找出问题所在。

我还尝试明确检查if LOCAL_CSS == True如果上面的 if 语句仅仅因为变量存在而被评估为 True 。

无论如何,我希望这是迄今为止我错过的关于 django 的一个奇怪的细节,或者有更多经验的人会立即看到我做错了什么。

如果您认为我以错误的方式处理此问题,请随时仔细阅读我没有接受者的原始问题: https ://stackoverflow.com/questions/11975054/django-recipe-for-local-css-and- local-js-like-settings-local-py-for-app-with-m


回答!- 三个独立的问题

通常情况下,多个错误步骤似乎是一个更简单的单一问题

最终的工作实际上非常简单:

supervacuo 的建议和一些争论之后,我添加了一个上下文处理器,templates_local/context.py:

import os.path

install_dir = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
localcss = os.path.join(install_dir, 'templates_local', 'local.css')
localjs =  os.path.join(install_dir, 'templates_local', 'local.js')

def local_static(context):
    return {
        'LOCAL_CSS': localcss if os.path.exists(localcss) else False,
        'LOCAL_JS':  localjs  if os.path.exists(localjs)  else False,
        }

并添加"rooibos.templates_local.context.local_static",到 settings.py 文件中预先存在的 TEMPLATE_CONTEXT_PROCESSORS 列表中。

我只需要将模板中的 if 语句切换为 if not:

{% if LOCAL_CSS != False %}
    {% compress css  %}
        {% include LOCAL_CSS %}
    {% endcompress  %}
{% endif %}

什么地方出了错?

问题 1 - 我对模板上下文中可用的内容感到困惑

查看supervacuo 的第一个建议

问题 2 - 缺乏经验/熟悉环境

我没有发现/怀疑在 django 的上下文中,像 os.path.exists() 这样的方法是从 manage.py 的位置执行的,而不是你调用它的 path/file.py (这在事后诸葛亮)

问题 3 - 有缺陷的逻辑,太简单的方法,也许是别的

我怀疑如果文件不存在,TEMPLATE_DEBUG = True您可能无法包含路径字符串(例如)而不会出现错误。{% include "../templates_local/local.css" %}

但无论如何,它现在的工作方式(确定文件存在,然后保存绝对路径或 False 作为模板变量似乎是一个更强大的解决方案,并且在模板中更具可读性。

再次感谢 supervacuo,您的建议和评论非常有用——我觉得我因为他们而对 django 有了一些了解!

4

2 回答 2

3

(根据您的评论回复)

您实际上并没有将新LOCAL_CSS变量传递给模板,这绝对是您在继续之前需要解决的问题。默认情况下,其中的一些settings.py是可用的(例如 MEDIA_URL),但这些是由Django 的默认上下文处理器添加的,在TEMPLATE_CONTEXT_PROCESSORS. {{ MEDIA_URL }}是可用的,例如,因为django.core.context_processors.media.

那么,向每个页面添加上下文变量的最佳方法是自定义上下文处理器。类似于以下内容:

# app/context.py
from django.conf import settings

def local_static(context):
    # Make sure to return a dictionary
    return {
        'LOCAL_CSS': settings.LOCAL_CSS,
        'LOCAL_JS': settings.LOCAL_JS,
    }

# settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
    # ... keep the defaults
    'app.context.local_static'
)
LOCAL_CSS = 'foo'

# template.html
{{ LOCAL_CSS }}
{# should output "foo" #}

为此,您应该使用aRequestContext而不是plainContext来呈现您的模板;Django 文档说:

如果您使用 Django 的render_to_response()快捷方式来使用字典的内容填充模板,则Context默认情况下您的模板将被传递一个实例(而不是 a RequestContext)。要RequestContext在模板渲染中使用 a,请将可选的第三个参数传递给render_to_response()RequestContext实例

事实上,最简单的方法是使用render()而不是render_to_response()

于 2012-08-22T22:46:48.380 回答
1

好的,这个兔子洞越来越深了(希望我们可以编辑现有的问题并回答一些普遍有用的东西——一旦这一切都整理好了)。

相对路径(如"local.css"os.path.exists()是相对于您在运行时所在的目录进行解释的runserver。因此,尽管os.path.exists('local.css') == True在该目录中,您的调试内容需要指定相对路径manage.py(或为简单起见将它们设为绝对路径)。

我不确定try .. finally在这里做什么,但也许只是这样做:

from django.conf import settings
import os

def local_static(context):
    # Make sure to return a dictionary
    return {
        'LOCAL_CSS': '/path/to/local.css' if os.path.exists('/path/to/local.css') else False,
        'LOCAL_JS': '/path/to/local.js' if os.path.exists('/path/to/local.js') else False,
        }

一旦你确认它按预期工作,从那里开始构建(在etc.if os.path.exists()中进行测试)local_settings.py

于 2012-08-23T23:50:34.440 回答