Let my model Notification model be:
Class Notification(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='notifications',
on_delete=models.CASCADE)
notif = models.CharField(max_length=255)
date_created = models.DateTimeField(auto_now_add=True)
The database rows are as:
id | user | notif |
------------------------------------
1 john doe liked your pic
2 john doe commented on your pic
3 james liked your pic
4 james commented on your pic
5 john doe pinged you
6 john doe showed interest
7 john doe is busy
Basically, I am trying to join consecutive rows by user
The above notifications then are to be shown as:
2 notifications from john doe
2 notification from james
3 notofications from john doe
instead of
5 notifications from john doe
2 notification from james
or
1 notifications from john doe
1 notifications from john doe
1 notification from james
1 notification from james
1 notofications from john doe
1 notofications from john doe
1 notofications from john doe
In order to achieve this, we are looking for a dictionary like:
{
"john doe": ["notif1", "notif2"],
"james": ["notif1", "notif2"],
"john doe": ["notif1", "notif2", "notif3"] #duplicate key.
}
But, that's not possible as duplicate keys are not allowed. Hence I am going with array of tuples instead.
[
('john doe', ['notif1', 'notif2']),
('james', ['notif1', 'notif2']),
('john doe', ['notif1', 'notif2', 'notif3']),
]
So, we first sort the Notifications by date_created. Then we use itertools.groupby to make groups per user.
from itertools import groupby
from operator import attrgetter
qs = Notification.objects.select_related('user').order_by('date_created')
notifs= [(u, list(nf)) for (u, nf) in groupby(qs, attrgetter('user'))]
You have everything sorted as needed in notifs.
Done!
5 notifications from John Doe, 2 Notification from James.