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
|