5

I'm trying to integrate this snippet into our Django project:

It's just custom HTML and CSS for messages.

The html looks like this:

<div class="bs-calltoaction bs-calltoaction-success">
    <div class="row">
        <div class="col-md-9 cta-contents">
            <h1 class="cta-title">Its a Call To Action</h1>
            <div class="cta-desc">
                <p>Describe the action here.</p>
                <p>Describe the action here.</p>
                <p>Describe the action here.</p>
            </div>
        </div>
        <div class="col-md-3 cta-button">
            <a href="#" class="btn btn-lg btn-block btn-default">Go for It!</a>
        </div>
     </div>
</div>

So if I want to integrate it with messages framework, I can do:

{% for message in messages %}
    <div class="bs-calltoaction bs-calltoaction-{{ message.tags }}">
        <div class="row">
            <div class="col-md-9 cta-contents">
                {{ message }}
            </div>
            <div class="col-md-3 cta-button">
                <a href="#" class="btn btn-lg btn-block btn-default">Go for It!</a>
            </div>
         </div>
    </div>
{% endfor %}

But I would like to specify header <h1> and list of sub-messages <p> so I need to add to message something like dictionary which can hold additional attributes like {'title':'This is a title','submessages':[1,2,3]} so I can do:

{% for message in messages %}
    <div class="bs-calltoaction bs-calltoaction-{{ message.tags }}">
        <div class="row">
            <div class="col-md-9 cta-contents">
                <h1 class="cta-title">{{ message.title }}</h1>
                <div class="cta-desc">
                    <p>{{ message.submessages.0 }}</p>
                    <p>{{ message.submessages.1 }}</p>
                </div>
            </div>
            <div class="col-md-3 cta-button">
                <a href="#" class="btn btn-lg btn-block btn-default">Go for It!</a>
            </div>
         </div>
    </div>
{% endfor %}

Is it possible using Django messages? Or would you suggest another approach? I can pass such variables into the context but I would like to use messages if possible.

Jens
  • 20,533
  • 11
  • 60
  • 86
Milano
  • 18,048
  • 37
  • 153
  • 353
  • Too bad `extra_tags` attribute is a string and not a dict. It's almost impossible to pass structured data this way. I don't understand this choice. – David Dahan Aug 03 '22 at 20:32

2 Answers2

8

You can get certain amount of freedom using the extra_tags messages attribute.

See https://docs.djangoproject.com/en/1.11/ref/contrib/messages/#adding-extra-message-tags

So you could have different extra_tags for different calls to action, e.g.

# views.py
messages.success(request, 'You have signed up', extra_tags='suggest_upgrade')

or:

messages.success(request, 'You have signed up', extra_tags='suggest_share')

and then:

{% for message in messages %}

    {% if 'suggest_upgrade' in message.extra_tags %}
        <h1>Get these extra features</h1>
        <p>info here</p>
    {% elif 'suggest_share' in message.extra_tags %}
        <h1>Share with friends</h1>
        <p>other info here</p>
    {% endif %}

{% endfor %}

You could even pass a submessage as the tag itself although it’s probably not designed for that purpose:

messages.success(request, 'Main message here', extra_tags='submessage here')

and then:

{% for message in messages %}

    <h1>{{ message }}</h1>
    <p>{{ message.extra_tags }}</p>

{% endfor %}
birophilo
  • 912
  • 10
  • 20
3

Message doesn't necessary needs to be a string. In your case, using a dictionary would work just fine:

messages.success(request, {'title':'This is a title','submessages':[1,2,3]})

and then in your template:

{% for message in messages %}
    <div class="bs-calltoaction bs-calltoaction-{{ message.tags }}">
        <div class="row">
            <div class="col-md-9 cta-contents">
                <h1 class="cta-title">{{ message.message.title }}</h1>
                <div class="cta-desc">
                    <p>{{ message.message.submessages.0 }}</p>
                    <p>{{ message.message.submessages.1 }}</p>
                </div>
            </div>
            <div class="col-md-3 cta-button">
                <a href="#" class="btn btn-lg btn-block btn-default">Go for It!</a>
            </div>
         </div>
    </div>
{% endfor %}
xpy
  • 5,481
  • 3
  • 29
  • 48
  • Tested in django 2.2.1 and its converting message to string so it does not work anymore. – jaanus Feb 01 '21 at 09:01
  • @jaanus Indeed, also it is not the best approach. – xpy Feb 01 '21 at 09:11
  • 1
    Whats the solution for this in Django 4 ? – anjanesh Aug 22 '22 at 14:53
  • @anjanesh I am not sure if there is an elegant solution for this. You could always JSON stringify it or serialize it, but still, it is not elegant. OR you can just create a wrapper for the messages and then use https://docs.djangoproject.com/en/4.1/topics/templates/#django.template.loader.render_to_string to create the string that you will pass to the message. – xpy Aug 23 '22 at 11:41
  • I ended up using JavaScript & AplineJS for this - https://anjane.sh/3AFzzbn – anjanesh Aug 23 '22 at 18:27