13

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.

6 Answers 6

10

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer but that means that I have to iterate through the errors several times to output all the errors and then all the success messages. I wanted a way to grab all the errors by themselves.
The docs say you have to iterate through all messages anyway or you will have them left over.
5

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.

Comments

5

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

1 Comment

Do you really need to perform the loop again? Looks like doing an {% elif 'error' in message.tags %} (or a completely independent if after the first one) in the first loop should also work, no?
1

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

2 Comments

Good answer for displaying all the messages
Honestly, best answer I've seen on this topic.
1

you can use following to check message tags.

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

Comments

0

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

1 Comment

you are making simple things complicated

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.