Anjanesh Lekshminarayanan


Passing a dictionary to Django's messages framework

Sending in a dictionary as an argument to the message string in messages.add_message

Anjanesh Lekshminarayanan's photo
Anjanesh Lekshminarayanan
·Aug 23, 2022·

3 min read

Subscribe to my newsletter and never miss my upcoming articles

In order to display some 'flash' message after a form submission like a success message or an error message we make use of messages framework which is built-in in Django.

I was doing a return redirect('dashboard') from a job posting form. Thing is, I am redirecting to the dashboard from many such forms which are located in different pages. I wasn't redirecting to a dedicated page unique to each form submission like job post, contact etc - as a result, I don't know details such as, from which page its come from, or other success form submission data, specific to the page, that are required to be shown on the dashboard.

In :

from django.contrib import messages

In class AddJob(LoginRequiredMixin, generic.CreateView): of :

def form_valid(self, form):
    form.instance.user = self.request.user
    super(AddJob, self).form_valid(form)

    data = {
        "section": "job",
        "message": "You've successfully posted a job - thank you - it'll be available post approval",
        "some_other_data_1": "foo",
        "some_other_data_2": "bar"

    messages.add_message(self.request, messages.SUCCESS, data, extra_tags="dictionary")

    return redirect('dashboard')

An example of sending in a message is as follows :

messages.add_message(request, messages.INFO, 'Hello world.')

The actual message, 'Hello world.' is a string.

There's one slight problem using this method of sending in data which is a dictionary - it'll be converted to a string and the resultant message argument would be

'{"section": "job", "message": "You\'ve successfully posted a job - thank you - it\'ll be available post approval", "some_other_data_1": "foo", "some_other_data_2": "bar" }'

which is not a dictionary but rather a string containing the dict.

I searched for a lot of workarounds to pass in an actual dict to add_message but in vain.

{{ message }} below will output the string representation of the python dictionary data.

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

So we won't be able to do things like {{ message.section }} or {{ message.message }} or {{ message.some_other_data_1 }}

Enter JavaScript :

Load AlpineJS in your base HTML template : (this is only to make life simpler instead of doing something like divElement.innerHTML = data.message etc or using jQuery)

<script src="" defer></script>

Now in <app>/templates/dashboard.html, message.tags will be 'dictionary success' since we passed in extra_tags="dictionary" to messages.add_message before.

    {% if messages %}
        {% for message in messages %}
            {% if 'dictionary' in message.tags %}
                    let data = {{ message | safe }};
                <div x-data="{ message_data : data }">
                    <h3>Message :</h3>
                    <p x-text="message_data.section"></p>
                    <p x-text="message_data.message"></p>
                    <p x-text="message_data.some_other_data_1"></p>
            {% else %}
                <div>{{ message }}</div>
            {% endif %}
        {% endfor %}
    {% endif %}

x-text="message_data.section" will have the element's (in this case the p tag) content to have the value of message_data.section which is job

Share this