Приложение django: как прочитать немного html в javascript
У меня есть приложение django, в котором есть проблема с дизайном, которую я хотел бы исправить: скрипт хочет ввести фрагмент html, содержащий теги django.
То, что мы имеем сейчас, работает, но имеет некоторые неприятные аспекты:
- Сохраните скрипт в виде html-фрагмента, который является ничем иным, как скриптом: первая строка
<script>
, а последняя строка закрывает этот скрипт. - Страницы, использующие этот скрипт, импортируют его так же, как любой html-фрагмент.
- Этот скрипт присваивает локальной переменной значение html, но в виде длинной строки, затем находит, где требуется html-бит, и вызывает insertAdjacentHTML, чтобы вставить его.
Итак, фрагмент представляет собой html-файл, который не содержит ничего, кроме скрипта, а этот скрипт, в свою очередь, содержит жестко запрограммированный html в виде строки. Это затрудняет чтение и не позволяет нашим редакторам javascript и html работать с этим фрагментом. Но код работает, и скрипт можно использовать на любой странице, просто импортировав один фрагмент.
Есть ли более чистое решение? Моим идеальным решением было бы:
- Сохраните html-бит в html-файле.
- Сохраните скрипт в файле .js.
- Разрешить страницам, использующим скрипт, просто загружать скрипт.
Я пробовал следующие способы, но ни один из них не работает и не отвечает всем этим целям:
1: Преобразуйте html-фрагмент в статический javascript-файл, сохранив при этом жестко запрограммированный html-код внутри. Загрузите его как любой статический скрипт.
К сожалению, это не удается, поскольку теги django не заменяются. Кроме того, в файле javascript по-прежнему присутствует жестко запрограммированный html.
2: Сохраните html-код в виде файла и прочитайте его с помощью вызова fs. Очевидно, что вызовы fs недоступны в нашей среде, и я не уверен, что стоит добавлять необходимую дополнительную библиотеку.
3: Используйте модель предметной области, чтобы получить доступ к html-фрагменту следующим образом:
- Переместите html-фрагмент в новый html-фрагмент, поместив его в новый скрытый div с уникальным идентификатором.
- Пусть страница, на которой загружается скрипт, сначала содержит html-фрагмент, в конце раздела
{% block content %}
, а также содержит html-фрагмент скрипта (если бы я мог заставить это работать, я бы попробовал перенести его в статический js-файл, но по одному изменению за раз). - Пусть скрипт использует модель домена, чтобы получить html-бит, содержащий div, получить html-код в виде строки, используя
innerHTML
, затем удалите скрытый div (чтобы скрытый html-бит не испортил работу приложения).
В модульных тестах это приводит к сбою, который показывает, что новый html-бит не удаляется. Но я скажу, что когда я запускаю приложение локально, оно, похоже, работает, и теги django обрабатываются правильно. Кроме того, если я удалю "скрытый", я не увижу html-код при взаимодействии с сервером. Так что я не совсем уверен, что происходит. Но я думаю, что неработающие тесты показывают, что это решение не совсем корректно.
В любом случае, у этого решения есть свои проблемы:
- Добавлять нежелательный html-код на страницу рискованно (как показывают неработающие тесты).
- Для этого требуется, чтобы любая страница, загружающая скрипт, также импортировала соответствующий фрагмент html.
Я мог бы изменить скрытый html-код так, чтобы он не мешал (т.е. выбрать новые имена, а затем отредактировать их в скрипте), но это кажется уродливым и чреватым ошибками.
Есть идеи для более эффективного решения? Я перепробовал множество способов поиска в Интернете, но подозреваю, что неправильно задаю вопрос.
Чтобы устранить проблему с дизайном в вашем приложении Django, в которое вы хотите внедрить HTML, содержащий теги шаблонов Django, с помощью сценария JavaScript, вы можете использовать более простой подход. Цель состоит в том, чтобы разделить HTML и JavaScript в соответствующих файлах, обеспечивая при этом правильную обработку тегов шаблона Django. Вот пошаговое решение:
Шаг 1: Сохраните HTML-код в шаблоне Django Создайте шаблон Django: Сохраните фрагмент HTML-кода в отдельном файле шаблона Django. Это позволяет Django обрабатывать теги шаблона.
<!-- templates/snippets/my_snippet.html -->
<div id="my-snippet">
<!-- Your HTML with Django template tags -->
<p>{{ some_variable }}</p>
</div>
Шаг 2: Создайте файл JavaScript Создайте файл JavaScript: Сохраните логику JavaScript в отдельном js-файле. Этот скрипт будет отвечать за ввод HTML-кода в нужное место.
// static/js/inject_snippet.js
document.addEventListener('DOMContentLoaded', function() {
// Fetch the HTML snippet from the server
fetch('/get-snippet/')
.then(response => response.text())
.then(html => {
// Find the target element where you want to inject the HTML
const targetElement = document.getElementById('target-element-id');
if (targetElement) {
// Insert the HTML snippet
targetElement.insertAdjacentHTML('beforeend', html);
}
})
.catch(error => console.error('Error fetching the snippet:', error));
});
Шаг 3: Создайте представление Django для отображения фрагмента HTML Создайте представление Django: создайте представление в Django, которое отображает фрагмент HTML. Это представление обработает теги шаблона и вернет отображенный HTML-код.
# views.py
from django.shortcuts import render
def get_snippet(request):
# Render the HTML snippet with any context variables
context = {
'some_variable': 'Some Value'
}
return render(request, 'snippets/my_snippet.html', context)
Map the View to a URL: Add a URL pattern to map the view to a specific URL.
# urls.py
from django.urls import path
from .views import get_snippet
urlpatterns = [
path('get-snippet/', get_snippet, name='get_snippet'),
]
Шаг 4: Включите JavaScript в свой шаблон Включите JavaScript в свой шаблон: Включите файл JavaScript в свой основной шаблон или в конкретный шаблон, в котором вам нужен фрагмент кода.
<!-- templates/base.html or specific template -->
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Other head elements -->
<script src="{% static 'js/inject_snippet.js' %}" defer></script>
</head>
<body>
<!-- Your content -->
<div id="target-element-id">
<!-- The HTML snippet will be injected here -->
</div>
</body>
</html>
Пояснение Разделение задач: Разделяя HTML и JavaScript на соответствующие файлы, вы сохраняете четкую структуру и упрощаете чтение и поддержку кода. Обработка шаблона Django: Фрагмент HTML обрабатывается Django, гарантируя корректное отображение всех тегов шаблона. Динамическое внедрение: JavaScript извлекает обработанный фрагмент HTML с сервера и вводит его в нужное место в DOM. Возможность повторного использования: файл JavaScript может быть включен в любой шаблон, что позволяет повторно использовать решение на разных страницах. Такой подход гарантирует четкое разделение HTML и JavaScript и правильную обработку тегов шаблона Django. Это также позволяет избежать проблем, с которыми вы сталкивались при тестировании жестко закодированных HTML-строк и нежелательных HTML-элементов.
Я последовал замечательному совету Абдулазиза Барката и изменил содержимое <div id=...>
на <template id=...>
, и все заработало. Я получаю html-строку, получая innerHTML элемента template, и нет необходимости пытаться удалить какие-либо элементы со страницы.
Я также изменил html-фрагмент, чтобы загрузить соответствующий статический файл javascript, поэтому html, использующий скрипты, может просто импортировать этот фрагмент.
Примечание: не устанавливайте shadowrootmode
свойство <template>
для этого варианта использования. Это все испортило для меня (независимо от того, установил ли я значение "открыто" или "закрыто"), и в этом нет необходимости.