Сортировка сообщений по тегам в шаблоне django
Я получаю список сообщений, каждое сообщение имеет тег. Это может быть "info", "warning", "danger" и "spreadsheet". Мне нужно отобразить сначала первые три, а затем электронные таблицы, но в свернутом виде, если их больше 3.
Итак, для всех сообщений, кроме таблицы, шаблон следующий:
<div class="row banner">
<ul class="banner-message">
{% for message in messages %}
<li{% if message.tags %} class="banner-message--{{ message.tags }}" {% else %} class="banner-message--info" {% endif %}>
<div class="message-content">
<p>{{ message|safe }}</p>
<span class="close">×</span></div>
</li>
{% endfor %}
</ul>
</div>
Для тегов с тегом "spreadsheet" шаблон имеет следующий вид:
<div class="row banner">
<ul class="banner-message">
{% for message in messages %}
<li class="{% if forloop.counter >= 3 %}collapsible_content{% endif %} banner-message--info">
<div class='message-content'>
<p>{{ message|safe }}</p>
<span class="close">×</span>
</div>
</li>
{% endfor %}
{% if messages|length > 3 %}
<button id="show_more" class="btn btn-secondary collapsible_button">Show all</button>
{% endif %}
</ul>
</div>
Показывается кнопка для сообщений электронной таблицы, если их больше 3, и показывает их все при нажатии.
Проблема в том, что я получаю эти сообщения в одном массиве, и у меня нет гарантии, что они не будут перемешаны в разном порядке.
Мне нужно как-то отсортировать их с помощью message.tags в два отдельных массива? Или использовать какой-нибудь умный if, но я не могу понять, как этого добиться в шаблоне. Не могли бы вы помочь?
EDIT: Думаю, я мог бы сделать это в javascript ДО рендеринга страницы, но я не уверен, как убедиться, что javascript будет вызван в нужное время, и как прочитать {{ messages }} в javascript. Есть ли такое решение?
вы можете разделить сообщения на два разных набора запросов. В вашем файле views.py:
context['messages'] = messages.filter(tags__in = ['info','warning','danger']).order_by('tags')
context['spreadsheet'] = messages.filter(tags = 'spreadsheet')
В вашем шаблоне:
<div class="row banner">
<ul class="banner-message">
{% for message in messages %}
<li{% if message.tags %} class="banner-message--{{ message.tags }}" {% else %} class="banner-message--info" {% endif %}>
<div class="message-content">
<p>{{ message|safe }}</p>
<span class="close">×</span></div>
</li>
{% endfor %}
</ul>
</div>
<div class="row banner">
<ul class="banner-message">
{% for message in spreadsheet %}
<li class="{% if forloop.counter >= 3 %}collapsible_content{% endif %} banner-message--info">
<div class='message-content'>
<p>{{ message|safe }}</p>
<span class="close">×</span>
</div>
</li>
{% endfor %}
{% if messages|length > 3 %}
<button id="show_more" class="btn btn-secondary collapsible_button">Show all</button>
{% endif %}
</ul>
</div>
get_messages - это служебная функция, а не метод класса. Подробнее о том, как ее использовать, вы можете прочитать в документации здесь.
По вашему мнению, вы можете сделать:
from django.contrib.messages import get_messages
...
storage = get_messages(request)
messages = []
spreadsheet_messages = []
for message in storage:
tags = message.tags
if ("info" in tags) or ("warning" in tags) or ("danger" in tags):
messages.append(message)
if "spreadsheet" in tags:
spreadsheet_messages.append(message)
context["messages"] = messages
context["spreadsheet"] = spreadsheet_messages
...