djangobootstrap-toast

Django, Bootstrap toast appears whenever I refresh the page instead of when needed


I want to make a toast appear only when a file has been processed. Currently I check from the model.py whether another file exists or not. If it does, the file has been processed. Else not if not.

def status(self):
    if os.path.exists(...)):
        return "processed"
    else:
        return "unprocessed"

I'm not sure if it's right to check from model.py.

As for my HTML file, I have set the following.

{% for td in user.userlist.all %}
  {% if td.status == 'processed' %}
      <div class="toast" drole="alert" data-autohide="false" ... >
        <div class="toast-header">
          <strong class="mr-auto">{{ td.status }}</strong>
          <small class="text-muted">just now</small>
          <button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="toast-body">
          The file was {{ td.status }}
        </div>
      </div>
  {% endif %}
{% endfor %}

This works fine whenever it detects the word 'process', but the toast appears everytime I refresh since it detects 'process' repeatedly.

I want the toast appear only once when the file has actually processed instead of looking for the word 'process'.

Any suggestions are highly appreciated.

[SOLVED]

Added something like this on views.py

def process(request, obj_id):
    if os.path.exists('...'):
        messages.success(request, 'processed')

And on the HTML file, had to take it out of the for loop.

{% if messages %}
  <ul class="messages">
    {% for message in messages %}
        <div class="toast" drole="alert" data-autohide="false" ... >
          <div class="toast-header">
            <strong class="mr-auto">Processed</strong>
            <small class="text-muted">just now</small>
            <button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="toast-body">
            {{ message }}
          </div>
        </div>
    {% endfor %}
  </ul>
{% endif %}

Solution

  • You can use the built-in messages framework to display toasts, that will give you better control of when and what to display.

    You just need to add the message in your view:

    messages.success(request, 'File processed')
    

    And then display the messages in your template. You can even have that messages showing component included in your base template, and use the same component through all your different views. I use something like this (you'll need to adapt it to your Bootstrap specifics):

       <div class="toast-messages" id="main-toasts">
           {% for message in messages %}
            <div class="toast {{ message.tags }}" role="alert">
                {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}<strong>Ouch!</strong> {% endif %}
                {{ message }}
            </div>
            {% endfor %}
            {% block toast_messages %}{% endblock toast_messages %}
       </div>