在CSS档案中使用Django范本语法

时间:2019-03-13 14:46:44

标签: css django django-templates

我有一个css文件 home_global.css ,其中包含以下内容:

body {
    background-image: url("{% static 'citator/citator.jpg' %}");
}

此静态文件的加载方式为:

<link rel="stylesheet" href="{% static 'citator/home_global.css' %}" type="text/css">

但是,预期背景图片的网址无法解析,但会按字面解析。我想做的是在css文件中启用Django模板语法。

请注意,静态网址等均已正确设置,并且该问题不涉及此问题。

这个问题与我一个月前问过的另一个问题非常相似: How to use django template syntax in static files

但是,这里提供的答案是 javascript 所特有的,尤其要注意的是,“防止这种情况的基本问题是将上下文传递给render()函数中提到的模板在视图(或任何其他函数中,其行为方式相同,例如render_to-response())。”

如果我正确理解这一点,则此处没有相同的限制。此外,我随后从Django文档中了解到可以在各种文本文档中使用Django模板语法。因此,在我看来,在 this 情况下,我想在css文件中使用它,这应该是可能的。那么,我该怎么做?

3 个答案:

答案 0 :(得分:3)

好了,一个半月后,我决定只浏览一下文档,看看我自己是否可以解决这个问题。我有一个可行的解决方案。这是这样做的方法。

步骤1:添加一些目录并在设置中设置一些新变量。

首先,我假设您已经具有用于静态文件的这样的目录结构:

/<app_name>/static/<app_name>

添加另一个名为“模板”的子目录。这是我们 we 制作模板的地方。这不是保存它们的地方。因此,您现在应该拥有这个:

/<app_name>/static/<app_name>/templates

在此目录中,添加您的CSS模板。这是我的示例,另存为“ test.css”:

{% load static %}
body {
    background-image: url("{% static 'citator/citator.jpg %}");
}

现在将这些变量添加到设置中。请注意,我只有一个应用。如果您有更多的话,请找到一种更易于管理的方法:

APP_NAME = "<your app's name>"
STATIC_TEMPLATE_PATH = os.path.join(BASE_DIR, APP_NAME, "static", APP_NAME, "templates")

接下来,我们需要编写一个自定义命令,该命令将在这些模板上运行Django模板引擎。为此,请导航至:

/<app_name>/management/commands

如果没有这些目录,请进行创建。

然后,您需要制作一个文件,在以下目录中将其命名为“ render_static_templates.py”:

from django.core.management.base import BaseCommand 
from django.template import engines
from <project_name>.settings import STATIC_TEMPLATE_PATH, APP_NAME
import glob 
import os

def find_templates(stem: str):
    """
    Custom template finder that just looks in 
    your new static templates directories for templates
    """
    leaf = "*"
    path = os.path.join(stem, leaf)
    all_templates = glob.glob(path)
    return all_templates


class Command(BaseCommand):
    def handle(self, *args, **options):

        # Get the file paths for all our new static templates:    
        all_templates = find_templates(STATIC_TEMPLATE_PATH)

        # See docs: https://docs.djangoproject.com/en/2.1/topics/templates/    
        django_engine = engines['django']

        for path in all_templates:
            template = django_engine.get_template(path)
            # Debug if you want. The URL should now be resolved in this print output.
            print(template.render())

            # Now we need to save the RENDERED template somewhere. I save it up one level from the templates folder, so that collectstatic can find it. You can put it elsewhere.
            leaf = path.split("/")[-1]
            save_path = os.path.join(APP_NAME, "static", APP_NAME, leaf)
            # Debug
            print(save_path)

            with open(save_path, "w") as f:
                f.write(template.render())

下一步是运行此新管理命令:

python manage.py render_static_templates

您现在应该可以在

中看到渲染的模板。
/app/static/app

下次运行

python manage.py collectstatic

假设您已正确设置STATIC_ROOT和STATIC_URL,则将呈现的模板移动到应有的位置。就我而言:

/static/<app_name>

从那里开始,将使用您用于投放的内容投放RENDERED模板。 (我使用白噪声)。如果一切顺利,您应该在页面上看到背景图片!

可能的改进: -更好的目录结构。 -集成到“ collect_static”命令中。

答案 1 :(得分:3)

正如您正确指出的那样,Django模板可以用于任何文本文件,而不仅仅是HTML。但是,您需要确保它们是由模板引擎呈现的,并提供了特定的URL和视图。

这样,您可以期望对所有变量和标签进行插值,尤其是用settings.STATIC_URL替换“静态”。 但是,我不会坚持在CSS文件本身的URL之前加上“ / static /” ...这会很欺骗,因为您宁愿动态呈现文件。

在实践中:

project / urls.py

console.log(selectedExperience.from.split('/')[0])) // 04

console.log(months) // [ { value : 1, name: "one"}
                          { value: 2, name: "two" }
                          { value: 4, name: "four" } ]

console.log(months.find(month => month.value === selectedExperience.from.split('/')[0])); // undefined

该视图相当琐碎,并已内联到urls.py中。 请注意,我还指定了适当的模仿类型'text / css'。

在这里,我在URL前面添加了一个'css /'前缀,但这不是必需的,并且您的项目中不需要“ css”文件夹; 只要确保模板引擎可以找到“ home_global.css”即可;也就是说,将其放在所有已安装应用程序的/ template /子文件夹中, 甚至在项目中(如果已列出已安装的应用程序中的项目):

project / templates / home_global.css

from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    ...
    path('css/home_global.css', TemplateView.as_view(
        template_name='home_global.css',
        content_type='text/css')
    ),
    ...
]

您可以通过使用浏览器导航到以下网址来立即检查结果:

{% load static %}

body {
    background-image: url("{% static 'citator/citator.jpg' %}");
}

呈现文档如下:

http://127.0.0.1:8000/css/home_global.css

并根据需要将其包含在主模板中:

body {
    background-image: url("/static/citator/citator.jpg");
}

是否需要渲染多个CSS文档,将文件名作为参数,然后对所有文档使用单个视图可能会比较方便。在这种情况下,为简单起见,我将选择基于函数的视图:

urls.py:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="/css/home_global.css" type="text/css">
    ...

其中:

views.py

from django.urls import path
from . import views

urlpatterns = [
    ...
    path('css/<str:filename>.css', views.css_renderer),
    ...
]

并在您的主模板中:

from django.shortcuts import render


def css_renderer(request, filename):
    return render(request, filename + '.css', {}, content_type="text/css")

答案 2 :(得分:0)

切掉CSS标记的特定部分,然后使用style标记添加到HTML文件中。快速修复并为我工作。

main.css

  ...

#banner {
    background-color: #e5474b;
    color: #f2a3a5;
    padding: 13em 0 11em 0;
    background-color: #0c0c0c;
    background-image: url("/images/banner.jpg"); <-- Remove this part and put under html
    background-size: cover;
    background-repeat: no-repeat;
    background-position: 15% left;
    text-align: right;
    position: relative;
    z-index: 9999;
}
  ...

index.html

<head>
  ...
  <style>
    #banner {
      background-image: url("{% static 'images/banner.jpg' %}");
    }
  </style>
 ...
</head>