Сортировка сообщений по тегам в шаблоне 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">&times;</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">&times;</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">&times;</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">&times;</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
...
        
Вернуться на верх