]> git.openstreetmap.org Git - osqa.git/blob - forum/models/question.py
better handling of the accepting answers workflow
[osqa.git] / forum / models / question.py
1 from base import *
2 from tag import Tag
3 from django.utils.translation import ugettext as _
4
5 question_view = django.dispatch.Signal(providing_args=['instance', 'user'])
6
7 class Question(QandA):
8     accepted_answer = models.OneToOneField('Answer', null=True, related_name="question_accepting")
9     closed          = models.BooleanField(default=False)
10     closed_by       = models.ForeignKey(User, null=True, blank=True, related_name='closed_questions')
11     closed_at       = models.DateTimeField(null=True, blank=True)
12     close_reason    = models.SmallIntegerField(choices=CLOSE_REASONS, null=True, blank=True)
13     subscribers     = models.ManyToManyField(User, related_name='subscriptions', through='QuestionSubscription')
14
15     # Denormalised data
16     answer_count         = models.PositiveIntegerField(default=0)
17     view_count           = models.IntegerField(default=0)
18     favourite_count      = models.IntegerField(default=0)
19     last_activity_at     = models.DateTimeField(default=datetime.datetime.now)
20     last_activity_by     = models.ForeignKey(User, related_name='last_active_in_questions')
21
22     favorited_by         = models.ManyToManyField(User, through='FavoriteQuestion', related_name='favorite_questions')
23
24     class Meta(QandA.Meta):
25         db_table = u'question'
26
27     @property
28     def headline(self):
29         if self.closed:
30             return _('[closed] ') + self.title
31
32         if self.deleted:
33             return _('[deleted] ') + self.title
34
35         return self.title
36
37     @property
38     def answer_accepted(self):
39         return self.accepted_answer is not None
40
41     def delete(self):
42         super(Question, self).delete()
43         try:
44             ping_google()
45         except Exception:
46             logging.debug('problem pinging google did you register you sitemap with google?')
47
48     def update_last_activity(self, user):
49         self.last_activity_by = user
50         self.last_activity_at = datetime.datetime.now()
51         self.save()
52
53     def activate_revision(self, user, revision):
54         super(Question, self).activate_revision(user, revision)
55         self.update_last_activity(user)
56
57     @models.permalink    
58     def get_absolute_url(self):
59         return ('question', (), {'id': self.id, 'slug': django_urlquote(slugify(self.title))})
60
61     def get_answer_count_by_user(self, user_id):
62         from answer import Answer
63         query_set = Answer.objects.filter(author__id=user_id)
64         return query_set.filter(question=self).count()
65
66     def get_question_title(self):
67         if self.closed:
68             attr = CONST['closed']
69         elif self.deleted:
70             attr = CONST['deleted']
71         else:
72             attr = None
73         if attr is not None:
74             return u'%s %s' % (self.title, attr)
75         else:
76             return self.title
77
78     def get_revision_url(self):
79         return reverse('question_revisions', args=[self.id])
80
81     def get_latest_revision(self):
82         return self.revisions.all()[0]
83
84     def get_related_questions(self, count=10):
85         cache_key = '%s.related_questions:%d:%d' % (settings.APP_URL, count, self.id)
86         related_list = cache.get(cache_key)
87
88         if related_list is None:
89             related_list = Question.objects.values('id').filter(tags__id__in=[t.id for t in self.tags.all()]
90             ).exclude(id=self.id).exclude(deleted=True).annotate(frequency=models.Count('id')).order_by('-frequency')[:count]
91             cache.set(cache_key, related_list, 60 * 60)
92
93         return [Question.objects.get(id=r['id']) for r in related_list]
94
95     def __unicode__(self):
96         return self.title
97
98 def question_viewed(instance, **kwargs):
99     instance.view_count += 1
100     instance.save()
101
102 question_view.connect(question_viewed)
103
104 class FavoriteQuestion(models.Model):
105     question      = models.ForeignKey('Question')
106     user          = models.ForeignKey(User, related_name='user_favorite_questions')
107     added_at      = models.DateTimeField(default=datetime.datetime.now)
108
109     class Meta:
110         unique_together = ('question', 'user')
111         app_label = 'forum'
112         db_table = u'favorite_question'
113
114     def __unicode__(self):
115         return '[%s] favorited at %s' %(self.user, self.added_at)
116
117     def _update_question_fav_count(self, diff):
118         self.question.favourite_count = self.question.favourite_count + diff
119         self.question.save()
120
121     def save(self, *args, **kwargs):
122         super(FavoriteQuestion, self).save(*args, **kwargs)
123         if self._is_new:
124             self._update_question_fav_count(1)
125
126     def delete(self):
127         self._update_question_fav_count(-1)
128         super(FavoriteQuestion, self).delete()
129
130 class QuestionSubscription(models.Model):
131     user = models.ForeignKey(User)
132     question = models.ForeignKey(Question)
133     auto_subscription = models.BooleanField(default=True)
134     last_view = models.DateTimeField(default=datetime.datetime.now())
135
136     class Meta:
137         app_label = 'forum'
138
139
140 class QuestionRevision(NodeRevision):
141     class Meta:
142         proxy = True
143