Arif
Arif

Reputation: 273

Displaying Django Messages Framework Messages

I have been using the Django Messaging Framework to display messages to a user in the template.

I am outputting them to the template like this:

<ul>
    {% for message in messages %}
        <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
    {% endfor %}
</ul>

This outputs all the messages, errors, warning, success etc. I was just wondering if anyone had any ideas how to display only the error messages something like:

<ul>
    {% for message in messages.errors %}
        <li>{{ message }}</li>
    {% endfor %}
</ul>

The best I have come up with so far is this:

{% if messages %}
    {% for message in messages %}
        {% if forloop.first %}
            {% if message.tags == 'error' %}
                <div class="error">
                    <ul>
            {% endif %}
        {% endif %}

        <li>{{ message }}</li>

        {% if forloop.last %}
                </ul>
            </div>
        {% endif %}
    {% endfor %}
{% endif %}

Any ideas? Thanks in advance.

Upvotes: 13

Views: 14096

Answers (6)

car3oon
car3oon

Reputation: 11

Of course you can do it with {% regroup %} tag but you have to use dictsort filter aswell if you want to work properly. So firstly, tags should be sort by name and then group:

{% if messages %}
    {% regroup messages|dictsort:"tags" by tags as message_list  %}

    {% for tags in message_list %}
        <div class="alert alert-{{ tags.grouper }}">
            <div class="container">
                <ul>
                    {% for message in tags.list %}
                        <li>
                              {{ message }}
                        </li>
                    {% endfor %}
                </ul>
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
            </div>
        </div>
    {% endfor %}
{% endif %}

Upvotes: 0

JordanChina
JordanChina

Reputation: 345

you can use following to check message tags.

{% if message.tags == "error" %} your code here {% endif %}

Upvotes: 1

Adri&#225;n
Adri&#225;n

Reputation: 6255

I managed with template tags only:

{% if messages %}
    {% regroup messages by tags as messages %}
    <div id="messages">
    {% for tags in messages %}
        <ul class="{{ tags.grouper }}">
            {% for message in tags.list %}
                <li>{{ message|capfirst }}</li>
            {% endfor %}
        </ul>
    {% endfor %}
    </div>
{% endif %}

The key is the {% regroup %} tag.

This still has an some issues because the tags attribute includes the extra_tags of the message so if you make use of it you will get additional <ul> groups.

In future versions (probably 1.7), there will be a level_tag attribute so that issue will be gone soon.


(As soon as the level_tag attribute is available)

{% if messages %}
    {% regroup messages by level_tag as messages %}
    <div id="messages">
    {% for level in messages %}
        <ul class="{{ level.grouper }}">
            {% for message in level.list %}
                <li>{{ message|capfirst }}</li>
            {% endfor %}
        </ul>
    {% endfor %}
    </div>
{% endif %}

Upvotes: 1

Pablo Carpio
Pablo Carpio

Reputation: 75

Reto's answer works for me in this way

{% for message in messages %}
    {% if 'success' in message.tags %}

        <div class="alert alert-success">
            <a class="close" href="#" data-dismiss="alert">×</a>
            <strong>Success!</strong>

                {{ message }}

        </div>
    {% endif %}
{% endfor %}

{% for message in messages %}
    {% if 'error' in message.tags %}
        <div class="alert alert-error">
            <a class="close" href="#" data-dismiss="alert">×</a>
            <strong>Error!</strong>

                {{ message }}

        </div>
    {% endif %}
{% endfor %}
{% for message in messages %}
    {% if 'info' in message.tags %}
        <div class="alert alert-info">
            <a class="close" href="#" data-dismiss="alert">×</a>
            <strong>INFO!</strong>

                {{ message }}

        </div>
    {% endif %}
{% endfor %}

Upvotes: 5

Reto Aebersold
Reto Aebersold

Reputation: 16624

You can put an ifequal:

<ul>
    {% for message in messages.errors %}
        {% if 'error' in message.tags %}<li>{{ message }}</li>{% endif %}
    {% endfor %}
</ul>

The mapping of message level to message tag can be configured with MESSAGE_TAGS.

Upvotes: 10

Ben
Ben

Reputation: 482

A bit of a faff, but you could probably achieve this by adding a custom template context processor (cf. https://docs.djangoproject.com/en/dev/ref/templates/api/ ) -- something like

def collect_error_messages(request):
    messages = get_messages(request)
    error_messages = [ m for m in messages if 'error' in m.tags]
    return {'error_messages': error_messages}

then add that to your TEMPLATE_CONTEXT_PROCESSORS list in settings.py, and then in templates you can do:

<ul>
    {% for message in error_messages %}
        <li>{{ message }}</li>
    {% endfor %}
</ul>

You could do a variation on the same to build a dict mapping error level to message, and then iterate through each dict.

Upvotes: 5

Related Questions