stephan
stephan

Reputation: 2403

How can I print the 'date received' only one time while using a for loop?

I am trying to group messages by received today, received yesterday, ect. To clarify, I am trying to have a single header that says "Today" and then list those messages underneath. I am NOT trying to print "Today" along with each message that was received on that day (which is currently what's happening).

I currently have the TODAY and YESTERDAY headers inside of my for loop so I understand that is why it is printing these headers for each mail message, but as previously stated I just want to print them one time. My question is, how can I achieve this using the code below? Do I need to make separate for loops for each time period (today, yesterday, last week, ect.), or is there a more efficient way to do this?

{% for message in messages %}
    {% if message.date - current.date < 24 hours %}
        TODAY
        Sent by: {{ message.sender }}
        {{ message.body }}
    {% elif message.date - current.date > 24 hours and message.date - current.date < 48 hours %}
        YESTERDAY
        Sent by: {{ message.sender }}
        {{ message.body }
    {% endif %}
{% endfor %}

Upvotes: 1

Views: 168

Answers (2)

Burhan Khalid
Burhan Khalid

Reputation: 174662

I am trying to group messages by received today, received yesterday

@Rohan gave you an answer but it will run the check on each loop even though you only print out the string once.

A better approach would be to organize your messages and order them by the date difference.

The best way to do this is to group the messages in the view before sending them to the template, like this:

from collections import defaultdict
from django.utils.timesince import timesince  # This will give us nice human
                                              # friendly date offsets

def some_view(request):

   messages = Message.objects.order_by('date')
   grouped_messaged = defaultdict(list)
   for message in messages:
      grouped_messages[timesince(message.date)].append(message)

   return render(request, 'template.html', {'all_messages': messages})

Now your template is a lot simpler:

<ul>
{% for header,messages in all_messages.items %}
    <li>{{ header }}
    <ul>
    {% for message in messages %}
        <li>{{ message.sender }} - {{ message.body }}</li>
    {% endfor %}
    </ul></li>
{% endfor %}
</ul>

Upvotes: 1

Rohan
Rohan

Reputation: 53366

You can use {{forloop.first}} for this. So your code can be updated to

{% for message in messages %}
    {% if message.date - current.date < 24 hours %}
        {% if forloop.first %}
            TODAY
        {% endif %}
    {% elif message.date - current.date > 24 hours and message.date - current.date < 48 hours %}
       {% if forloop.first %}
        YESTERDAY
       {% endif %}
    {% endif %}

    Sent by: {{ message.sender }}
    {{ message.body }}

{% endfor %}

Upvotes: 1

Related Questions