Evgenii Legotckoi
Evgenii Legotckoi05 липня 2018 р. 03:05

Django - Підручник 035. Різні шаблони для відтворення різних типів вмісту в результатах пошуку

Постійні відвідувачі сайту, які користуються пошуком на сайті, напевно, помітили, що відображення статей відрізняється від відображення коментарів у пошуковій видачі сайту. Це було досягнуто тим, що кожен тип контенту має власний шаблон для відображення, який підставляється при рендерингу сторінці залежно від того, який контент був знайдений у пошуку.

Подивимося на приклад видачі.

Бачите, тут подання коментаря відрізняється від статті, однак вони виводяться в рамках однієї пошукової видачі, як було зроблено у попередній статті.

Але це зроблено набагато витонченіше, ніж вибір через if else . Чесно, мені дуже подобається це рішення.


Для кожної моделі даних потрібно визначити поле, яке зберігає шлях до шаблону, щоб відобразити об'єкт цієї моделі. При цьому в кожній моделі це поле повинно мати одну й назву. Це дуже важливо.

Наприклад, зробимо так

class Article(models.Model):
    TEMPLATE_PREVIEW = 'home/article_preview.html'

class Comment(models.Model):
    TEMPLATE_PREVIEW = 'home/comment_preview.html'

class Topic(models.Model):
    TEMPLATE_PREVIEW = 'home/topict_preview.html'

class Post(models.Model):
    TEMPLATE_PREVIEW = 'home/post_preview.html'

У кожному цьому шаблоні ми можемо прописати своє власне відображення контенту, яке потрібно. Наприклад для статті

<div>
    <a href="{{ object.get_absolute_url }}"><h2>{{ object.itle }}</h2></a>
    {{ object.content|safe }}
    <p><a class="btn btn-default btn-sm" href="{{ object.get_absolute_url }}">Читать далее</a></p>
</div>

А для решти шаблонів можемо написати щось інше. Головне, щоб усі методи та поля, а також ім'я одиночного об'єкта було однаковим у всіх шаблонах.

А сам шаблон пошукової видачі може мати такий вигляд

{% load tz %}
{% load trans from i18n %}
{% load bootstrap_pagination from bootstrap4 %}
<div id="object-list">
    {% for object in object_list %}
        {% include object.TEMPLATE_PREVIEW %}
    {% empty %}
        <div class="card card-body mb-3">{% trans 'Ничего не найдено' %}</div>
    {% endfor %}
    {% bootstrap_pagination object_list pages_to_show="10" url=last_question %}
</div>

Нюанс полягає в тому, що ми звикли передавати в тег include рядкове ім'я шаблону, наприклад,

{% include 'home/article_preview.html' %}

Але ніхто не говорив, що тільки можна робити тільки так, а також ніхто не говорив, що ми не можемо взяти шлях до шаблону прямо з об'єкта, контент якого хочемо відрендерити. Тобто можна спокійно написати так

{% include object.TEMPLATE_PREVIEW %}

А якщо врахувати, що кожен об'єкт має свій TEMPLATE_PREVIEW, то файли там будуть підключатися різні, а значить кожен вид контенту матиме свій власний стиль малювання.

Для Django рекомендую VDS-хостинг TIMEWEB

Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

bernar92
  • 05 липня 2018 р. 03:58

интересное решение! интересно как реализовать такое через

Django REST

Evgenii Legotckoi
  • 05 липня 2018 р. 04:12

К сожалению, я сейчас мало использую django_rest_framework , но в будущем планирую значительную часть работы сайта переводить на него. Поэтому придумаю какое-нибудь подобное решение с использованием какого-нибудь JS-шаблонизатора.

Илья Чичак
  • 16 липня 2018 р. 22:01

Идея с классовыми параметрами интересна, однако при большом количестве элементов, это может занять значительные время. И дело даже не в решении, а в тэге include. При его использовании, шаблон будет искаться для каждого использования без учёта того, что это один и тот же шаблон. Если выводится 50, 100 или сколько-нибудь адекватное количество элементов - можно жить, но надо помнить, что в этом месте можно неслабо так порезаться.

И ещё одна проблема, что шаблоны не грузятся в память при запуске сервера. Так что без какого-нибудь кэширования этих шаблонов можно упереться в рендеринг, как в узкое место.
Evgenii Legotckoi
  • 17 липня 2018 р. 02:31

Согласен с вами!

И в каком-то смысле предвкушаю возможные проблемы. В данном варианте действительно потребуется как минимум кеширование, а как максимум дополнительное совершенствование, возможно стоило бы сделать рендеринг несколько иным способом, через классовый метод, например, возможно это позволит проще реализовать кеширование. Что думаете по этому поводу?
Для меня довольно большим плюсом в данном случае является увеличение скорости разработки за счёт шаблонизации и переиспользования повторяющихся частей кода.


bernar92
  • 17 липня 2018 р. 02:57

через классовый метод не обойтись

bernar92
  • 17 липня 2018 р. 03:01

мне кажется лучше это сделать на стороне клиента где при помощи vue js! а в модель сделать свойство по которому js будет генерирывать шаблон

Evgenii Legotckoi
  • 17 липня 2018 р. 03:04

А я вот планирую внедрять nunjucks, он очень сильно похож по синтаксису на шаблоны Django, и также поддерживает наследование шаблонов. Пробный запуск я уже делал и весьма понравилось. Но пока не внедрял в качестве боевого варианта, есть ещё где развернуться по оптимизациям на стороне сервера.

Илья Чичак
  • 17 липня 2018 р. 03:43
Я тут поэксперементировал. И что-то у меня не особо получилось сделать inclusion_tag и сунуть указатель на него в классовую переменную.
Я думаю, можно чуть глубже погрузиться в механизм шаблонных тэгов и попробовать сделать один тэг, в который передается объект модели, а он выбирает нужный шаблон и рендерит его.

либо не греть голову и сделать несколько тэгов - для каждой модели. а в классе модели определить какую-то переменную (например однобуквенную:) ) по которой бы определялось, какой тэг использовать. а если этот механизм часто используется, код выбора нужного тэга сунуть в еще один шаблон и сделать inclusion_tag. получится длинная цепочка, и, возможно, немного запутанная, но получится достаточно быстро
bernar92
  • 17 липня 2018 р. 04:00

запутанная... уже что-то пугает ....

Evgenii Legotckoi
  • 17 липня 2018 р. 05:02

Мысль о inclusion_tag мне весьма импонирует. Как вариант, можно хранить также путь к шаблону в параметре класса, а в данном теге уже искать шаблоны и делать кеширование, чтобы не скать каждый раз.

Также в качестве аргументов передавать в этот тег объект и имя параметра, а потом через getattr брать из объекта ту переменную... тогда получится один единственный тег для всех видов шаблонов, например TEMPLATE_PREVIEW, TEMPLATE_INFO и т.д.
Илья Чичак
  • 17 липня 2018 р. 05:29

Вообще, я полностью согласен. Подобное лучше всего отдать на откуп клиенту.

Илья Чичак
  • 17 липня 2018 р. 05:32

Запутанность - условная. Будет просто цепочка вызовов inclusion_tag-ов. Причём первое звено нужно лишь для возможности повторного использования. Если таковое не предполагается, можно опустить один уровень.

Evgenii Legotckoi
  • 17 липня 2018 р. 05:43

Думаю, что это всё равно стоит оставить для индексирующих роботов поисковых систем, которые испоьлзуют простые GET запросы. Они же AJAX не используют. Так что полностью уйти от этого не получится, если есть открытый контент на сайте.

Илья Чичак
  • 17 липня 2018 р. 05:53
тут все упирается в то, что вы хотите дать поисковым роботам. был у меня опыт проектирования страницы для роботов - сделал точки входа - со статикой для роботов и АПИ для JS клиента=) а отлавливал по UserAgent-у на уровне миддлвари (они особо не шифруются).
Если использовать JS, то можно и выводить порционно, подгружая новые объекты по мере скролла к концу текущего списка=) Тогда вообще нагрузки будет минимум. и отрисовывать будет моментально (при достаточно малых размеров порций данных).

А по поводу inclusion_tag-ов - не так просто заставить их работать из мета-программирования=( мне вот пришла в голову мысль, что можно было бы строить эти тэги в момент инициализации рантайма. тоесть где-то в templatetags модуле сканировать нужные модели, брать из них классовые переменные и на их основе создавать тэги. Но я бы поостерегся - очень много нюансов. и в первую очередь, можно очень быстро запутаться, а потом не разобраться=/

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
m
  • molni99
  • 26 жовтня 2024 р. 08:37

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:80бали,
  • Рейтинг балів4
m
  • molni99
  • 26 жовтня 2024 р. 08:29

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:20бали,
  • Рейтинг балів-10

C++ - Тест 003. Условия и циклы

  • Результат:42бали,
  • Рейтинг балів-8
Останні коментарі
i
innorwall10 листопада 2024 р. 23:52
Qt/C++ - Урок 025. Створення файлів проекту where to buy priligy It helps keep bones strong, nerves and muscles working properly, and blood sugar under control
i
innorwall10 листопада 2024 р. 21:03
Django - Підручник 029. Додавання приватних повідомлень і чатів на сайт - Частина 1 priligy at walgreens ortho ciprofloxacin tablet uses in telugu Republicans in Congress have chastised Obama s top health adviser, Health and Human Services Secretary Kathleen Sebelius, …
i
innorwall10 листопада 2024 р. 17:55
Як скопіювати файли в Linux In dogs, it is used to facilitate synchronized cardioversion of atrial fibrillation buy priligy usa
i
innorwall10 листопада 2024 р. 17:03
Як зробити гру за допомогою Qt - Урок 3. Взаємодія з іншими об&#39;єктами priligy otc I routinely do not tell patients and or parents of patients with atopic dermatitis to avoid glutamates in food
i
innorwall10 листопада 2024 р. 14:05
QML - Урок 020. Старт роботи з Android Manifest в Qt Creator PMID 34322115 Free PMC article pastillas priligy en mexico
Тепер обговоріть на форумі
i
innorwall11 листопада 2024 р. 00:34
добавить qlineseries в функции priligy dapoxetine amazon a Rates of overall CRA in respect of associated explanatory variables age at treatment and age at menarche
9
9Anonim25 жовтня 2024 р. 16:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
ИМ
Игорь Максимов03 жовтня 2024 р. 11:05
Реализация навигации по разделам Спасибо Евгений!
F
Fynjy22 липня 2024 р. 11:15
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

Слідкуйте за нами в соціальних мережах