Evgenij LegotskojJuly 5, 2018, 2:05 a.m.

Django - Tutorial 035. Different templates for rendering different types of content in the search results

Constant visitors of the site who use the search on the site, probably noticed that the display of articles differs from displaying comments in the search engine issue of the site. This was achieved by the fact that each content type has its own template for rendering, which is substituted for the rendering of the page, depending on what content was found in the search.

Let's look at the example of issuance.

You see, here the presentation of the comment differs from the article, but they are output in the framework of one search issue, as was done in the previous article.

But this is done much more elegantly than selecting via if else . Honestly, I myself really like this decision.

For each data model, you need to define a field that stores the path to the template to display the object of that model. In each model, this field must have the same name. It is very important.

For example, we do this

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'

In each of these templates, we can prescribe our own display of content, which is required. For example, for an article

<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>

And for all the other templates, we can write something else. The main thing is that all methods and fields, as well as the name of a single object, be the same in all templates.

And the pattern of search results may look like this

{% 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 'Nothing found' %}</div>
    {% endfor %}
    {% bootstrap_pagination object_list pages_to_show="10" url=last_question %}
</div>

The nuance is that we are used to passing the string name of the template to the include tag, for example so

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

But no one said that we can only do so, and also no one said that we can not take the path to the template directly from the object, the content of which we want to render. That is, you can safely write so

{% include object.TEMPLATE_PREVIEW %}

And if you consider that each object has its own TEMPLATE_PREVIEW , then the files there will be connected different, and that means each kind of content will have its own style of rendering.

For Django I recommend VDS-hosting TIMEWEB

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.
Support the author Donate

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

Django REST

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

Comments

Only authorized users can post comments.
Please, Log in or Sign up
Card image cap
Pulsum Via

Project for travelers from EVILEG.

Go
Fornex

Let me recommend you a great European Fornex hosting.

Fornex has proven itself to be a stable host over the years.

For Django projects I recommend VPS hosting

Following the link you will receive a 5% discount on shared hosting services, dedicated servers, VPS and VPN

View Hosting
Share on social networks
Donate

The EVILEG project has switched to a non-commercial basis and will develop solely on the enthusiasm of the site creator, the enthusiasm of users, donations and the hosting referral system

Thank you for your support

Available ways to support the project

PayPal

PatreonYandex.MoneyMore
DP

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:10points,
  • Rating points-10
VS

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:0points,
  • Rating points-10
VS

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
Last comments
Ds

Android and QML - Adding Splash Screen

Интересен формат иконки, если это png, то как решается проблема scalability? не растягивается ли лого на китайфонах с 1280х2500? У меня просто сплеш скрин с градиентом и логотипом, и вот несколь…
p

Qt/C++ - Lesson 023. Moving QGraphicsItem on QGraphicsScene with mouse help

FIGURE Abdominopelvic regions. Zjuaqd https://newfasttadalafil.com/ - Cialis Cialis Recommendations for preparing children and adolescents for invasive cardiac procedures a statement…
KG

How to use nested forms in Django

Спасибо за полезную статью. Подскажите пожалуйста, что делать если нужно реализовать большее количество вложенных форм? Например если на модель Address ссылается fk другой модели, на котору…

Qt/C++ - Lesson 051. QMediaPlayer – simple audio player

Не думаю, QMediaPlayer в один поток проигрывает. Если вам нужно одновременное воспроизведение нескольких аудиоисточников, то вам нужна Bass audio library , насколько знаю, её обычно и…
AG

Qt/C++ - Lesson 051. QMediaPlayer – simple audio player

есть такая вообще возможность ?
Now discuss on the forum
AB

Sorting the added QML elements in the ListModel

I am writing an alarm clock in QML, I am required to sort the alarms in ascending order (depending on the date or time (if there are several alarms on the same day). I've done the sorting …

Изменение поведения QGroupBox при клике на его чекбокс

Я вынес виджеты вынес за пределы QGroupBox в итоге.

QSqlRelatipnalTabelModel Qt 4.8.1 как получить id внешней связи?

Есть еще принципиально другой вариант решить раз и навсегда вопрос с полей id внешней связи. Это форкнуть Qt 4.8.1 QSqlTableModel, то есть создать свою ветку развития. Например создадим кл…

Добавление AndroidManifest.xml в cmake

Добрый день. Как добавить AndroidManifest.xml в cmake? Это не работвет set(ANDROID_PACKAGE_SOURCE_DIR ${PROJECT_SOURCE_DIR}/android CACHE INTERNAL "")set(ANDROID_BUID_DIR ${CMAKE_C…
s

Событие wheelEvent для виджета QLineEdit

вот что получилось: gui.py from PyQt5 import QtCore, QtGui, QtWidgets class LineEdit(QtWidgets.QLineEdit): def wheelEvent(self, event): #print("_") delta = 1 if e…
About
Services
© EVILEG 2015-2022
Recommend hosting TIMEWEB