annotate gpp/forums/unread.py @ 113:d97ceb95ce02

Forums: ForumLastVisit logic in place. Need to add code for topics and posts next.
author Brian Neal <bgneal@gmail.com>
date Sun, 11 Oct 2009 19:10:54 +0000
parents
children 535d02d1c017
rev   line source
bgneal@113 1 """
bgneal@113 2 This file contains routines for implementing the "has unread" feature.
bgneal@113 3 Forums, topics, and posts are displayed with a visual indication if they have
bgneal@113 4 been read or not.
bgneal@113 5 """
bgneal@113 6 import datetime
bgneal@113 7
bgneal@113 8 from forums.models import ForumLastVisit, TopicLastVisit, Topic
bgneal@113 9
bgneal@113 10
bgneal@113 11 THRESHOLD = datetime.timedelta(days=7)
bgneal@113 12
bgneal@113 13
bgneal@113 14 def get_forum_unread_status(qs, user):
bgneal@113 15 if not user.is_authenticated():
bgneal@113 16 for forum in qs:
bgneal@113 17 forum.has_unread = False
bgneal@113 18 return
bgneal@113 19
bgneal@113 20 now = datetime.datetime.now()
bgneal@113 21 min_date = now - THRESHOLD
bgneal@113 22
bgneal@113 23 # retrieve ForumLastVisit records in one SQL query
bgneal@113 24 forum_ids = [forum.id for forum in qs]
bgneal@113 25 flvs = ForumLastVisit.objects.filter(user=user,
bgneal@113 26 forum__in=forum_ids).select_related()
bgneal@113 27 flvs = dict([(flv.forum.id, flv) for flv in flvs])
bgneal@113 28
bgneal@113 29 for forum in qs:
bgneal@113 30 # Edge case: forum has no posts
bgneal@113 31 if forum.last_post is None:
bgneal@113 32 forum.has_unread = False
bgneal@113 33 continue
bgneal@113 34
bgneal@113 35 # Get the ForumLastVisit record
bgneal@113 36 if forum.id in flvs:
bgneal@113 37 flv = flvs[forum.id]
bgneal@113 38 else:
bgneal@113 39 # One doesn't exist, create a default one for next time,
bgneal@113 40 # mark it as having no unread topics, and bail.
bgneal@113 41 flv = ForumLastVisit(user=user, forum=forum)
bgneal@113 42 flv.begin_date = now
bgneal@113 43 flv.end_date = now
bgneal@113 44 flv.save()
bgneal@113 45 forum.has_unread = False
bgneal@113 46 continue
bgneal@113 47
bgneal@113 48 # If the last visit record was too far in the past,
bgneal@113 49 # catch that user up and mark as no unreads.
bgneal@113 50 if now - flv.end_date > THRESHOLD:
bgneal@113 51 forum.catchup(user, flv)
bgneal@113 52 forum.has_unread = False
bgneal@113 53 continue
bgneal@113 54
bgneal@113 55 # Check the easy cases first. Check the last_post in the
bgneal@113 56 # forum. If created after the end_date in our window, there
bgneal@113 57 # are new posts. Likewise, if before the begin_date in our window,
bgneal@113 58 # there are no new posts.
bgneal@113 59 if forum.last_post.creation_date > flv.end_date:
bgneal@113 60 forum.has_unread = True
bgneal@113 61 elif forum.last_post.creation_date < flv.begin_date:
bgneal@113 62 if not flv.is_caught_up():
bgneal@113 63 forum.catchup(user, flv)
bgneal@113 64 forum.has_unread = False
bgneal@113 65 else:
bgneal@113 66 # Going to have to examine the topics in our window.
bgneal@113 67 # First adjust our window if it is too old.
bgneal@113 68 if now - flv.begin_date > THRESHOLD:
bgneal@113 69 flv.begin_date = min_date
bgneal@113 70 flv.save()
bgneal@113 71 TopicLastVisit.objects.filter(user=user, topic__forum=forum,
bgneal@113 72 last_visit__lt=min_date).delete()
bgneal@113 73
bgneal@113 74 topics = Topic.objects.filter(creation_date__gt=flv.begin_date)
bgneal@113 75 tracked_topics = TopicLastVisit.objects.filter(user=user,
bgneal@113 76 topic__forum=forum, last_visit__gt=flv.begin_date)
bgneal@113 77
bgneal@113 78 # If the number of topics created since our window was started
bgneal@113 79 # is greater than the tracked topic records, then there are new
bgneal@113 80 # posts.
bgneal@113 81 if topics.count() > tracked_topics.count():
bgneal@113 82 forum.has_unread = True
bgneal@113 83 continue
bgneal@113 84
bgneal@113 85 tracked_dict = dict([(t.id, t) for t in tracked_topics])
bgneal@113 86
bgneal@113 87 for topic in topics:
bgneal@113 88 if topic.id in tracked_dict:
bgneal@113 89 if topic.update_date > tracked_dict[topic.id].last_visit:
bgneal@113 90 forum.has_unread = True
bgneal@113 91 continue
bgneal@113 92 else:
bgneal@113 93 forum.has_unread = True
bgneal@113 94 continue
bgneal@113 95
bgneal@113 96 # If we made it through the above loop without continuing, then
bgneal@113 97 # we are all caught up.
bgneal@113 98 forum.catchup(user, flv)
bgneal@113 99 forum.has_unread = False