Использовать синтаксис шаблона Django в файле CSS - PullRequest
5 голосов
/ 13 марта 2019

У меня есть файл css home_global.css , в котором содержится следующее:

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

Этот статический файл загружается с использованием:

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

Однако URL фонового изображения, как ожидается, не разрешается, а анализируется буквально. Я хотел бы включить синтаксис шаблона Django в файле css.

Обратите внимание, что статические URL-адреса и т. Д. Все настроены правильно, и этот вопрос не касается этого.

Этот вопрос очень похож на другой вопрос, который я сам задавал месяц назад: Как использовать синтаксис шаблона django в статических файлах

Тем не менее, ответ, предоставленный там, был специфичен для javascript , и, в частности, отметил, что «Основная проблема, которая предотвращает это, заключается в том, что контекст передается шаблону, который упоминается в вашей функции render () в представление (или любая другая функция ведет себя так же, например, render_to-response ()). "

Если я правильно понимаю, то же ограничение здесь не применяется. Кроме того, я впоследствии узнал из документации Django, что можно использовать синтаксис шаблона Django в различных текстовых документах. Поэтому мне кажется, что в этом случае, где я хочу использовать его в файле CSS, это должно быть возможно. Итак, как я могу это сделать?

Ответы [ 2 ]

3 голосов
/ 18 марта 2019

Как вы правильно заметили, шаблоны Django можно использовать для любого текстового файла, а не только для HTML. Однако вам необходимо убедиться, что они отображаются механизмом шаблонов, предоставляя конкретный URL и представление.

Таким образом, вы можете ожидать, что все переменные и теги будут интерполированы, и, в частности, будет заменено «static» на settings.STATIC_URL. Однако Я бы не стал настаивать на добавлении "/ static /" к URL самого CSS-файла ... это было бы обманом, так как вы скорее рендерили файл динамически.

На практике:

проект / urls.py

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')
    ),
    ...
]

Представление довольно тривиально и было встроено в urls.py. Обратите внимание, что я также указал соответствующий mimetype 'text / css'.

Здесь я добавил префикс «css /» к URL-адресу, но это не обязательно, и вам не нужна папка «css» в вашем проекте; просто убедитесь, что шаблонизатор может найти "home_global.css"; поместите его в / template / подпапку любого установленного приложения, или даже в проекте, если он указан среди установленных приложений:

Проект / шаблоны / home_global.css

{% load static %}

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

Вы можете сразу же проверить результат, перейдя по этому URL в браузере:

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

, который отображает документ следующим образом:

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

и включите его в основной шаблон при необходимости:

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

Если вам нужно отобразить много документов CSS , может быть удобно использовать имя файла как параметр, а затем использовать одно представление для всех документов. В этом случае я бы выбрал функциональное представление для простоты:

urls.py:

from django.urls import path
from . import views

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

где:

views.py

from django.shortcuts import render


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

и в вашем основном шаблоне:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="/css/home_global.css" type="text/css">
    <link rel="stylesheet" href="/css/another.css" type="text/css">
    <link rel="stylesheet" href="/css/yet_another.css" type="text/css">
    ...
3 голосов
/ 18 марта 2019

Хорошо, через полтора месяца я решил просто просмотреть документы и посмотреть, смогу ли я сам разобраться с этим.И у меня есть рабочее решение.Вот как это сделать.

ШАГ 1: добавьте несколько каталогов и настройте некоторые новые переменные в настройках.

Во-первых, я предполагаю, что у вас уже есть такая структура каталогов для статических файлов:

/<app_name>/static/<app_name>

Добавить еще один подкаталог с названием "шаблоны".Здесь мы сделаем наши шаблоны.Это не то место, где они будут сохранены.Теперь у вас должно быть следующее:

/<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 Template Engine на этих шаблонах.Для этого перейдите к:

/<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".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...