4 class QuestionManager(CachedManager):
5 def create_new(self, title=None,author=None,added_at=None, wiki=False,tagnames=None,summary=None, text=None):
11 last_activity_at = added_at,
12 last_activity_by = author,
19 question.last_edited_by = question.author
20 question.last_edited_at = added_at
21 question.wikified_at = added_at
25 # create the first revision
26 QuestionRevision.objects.create(
29 title = question.title,
31 revised_at = added_at,
32 tagnames = question.tagnames,
33 summary = CONST['default_version'],
38 question_view = django.dispatch.Signal(providing_args=['instance', 'user'])
40 class Question(Content):
41 title = models.CharField(max_length=300)
42 tags = models.ManyToManyField(Tag, related_name='questions')
43 answer_accepted = models.BooleanField(default=False)
44 closed = models.BooleanField(default=False)
45 closed_by = models.ForeignKey(User, null=True, blank=True, related_name='closed_questions')
46 closed_at = models.DateTimeField(null=True, blank=True)
47 close_reason = models.SmallIntegerField(choices=CLOSE_REASONS, null=True, blank=True)
48 followed_by = models.ManyToManyField(User, related_name='followed_questions')
49 subscribers = models.ManyToManyField(User, related_name='subscriptions', through='QuestionSubscription')
52 answer_count = models.PositiveIntegerField(default=0)
53 view_count = models.IntegerField(default=0)
54 favourite_count = models.IntegerField(default=0)
55 last_activity_at = models.DateTimeField(default=datetime.datetime.now)
56 last_activity_by = models.ForeignKey(User, related_name='last_active_in_questions')
57 tagnames = models.CharField(max_length=125)
58 summary = models.CharField(max_length=180)
60 favorited_by = models.ManyToManyField(User, through='FavoriteQuestion', related_name='favorite_questions')
62 objects = QuestionManager()
64 class Meta(Content.Meta):
65 db_table = u'question'
68 super(Question, self).delete()
72 logging.debug('problem pinging google did you register you sitemap with google?')
74 def get_tag_list_if_changed(self):
75 dirty = self.get_dirty_fields()
77 if 'tagnames' in dirty:
78 new_tags = self.tagname_list()
80 old_tags = dirty['tagnames']
84 old_tags = [name for name in dirty['tagnames'].split(u' ')]
90 tag = Tag.objects.get(name=name)
92 tag = Tag.objects.create(name=name, created_by=self.last_edited_by or self.author)
96 if not name in old_tags:
97 tag.used_count = tag.used_count + 1
102 for name in [n for n in old_tags if not n in new_tags]:
103 tag = Tag.objects.get(name=name)
104 tag.used_count = tag.used_count - 1
105 if tag.used_count == 0:
106 tag.mark_deleted(self.last_edited_by or self.author)
113 def save(self, *args, **kwargs):
114 tags = self.get_tag_list_if_changed()
115 super(Question, self).save(*args, **kwargs)
116 if not tags is None: self.tags = tags
118 def tagname_list(self):
119 """Creates a list of Tag names from the ``tagnames`` attribute."""
120 return [name for name in self.tagnames.split(u' ')]
122 def tagname_meta_generator(self):
123 return u','.join([unicode(tag) for tag in self.tagname_list()])
126 def get_absolute_url(self):
127 return ('question', (), {'id': self.id, 'slug': django_urlquote(slugify(self.title))})
129 def get_answer_count_by_user(self, user_id):
130 from answer import Answer
131 query_set = Answer.objects.filter(author__id=user_id)
132 return query_set.filter(question=self).count()
134 def get_question_title(self):
136 attr = CONST['closed']
138 attr = CONST['deleted']
142 return u'%s %s' % (self.title, attr)
146 def get_revision_url(self):
147 return reverse('question_revisions', args=[self.id])
149 def get_latest_revision(self):
150 return self.revisions.all()[0]
152 def get_last_update_info(self):
153 when, who = self.post_get_last_update_info()
155 answers = self.answers.all()
158 a_when, a_who = a.post_get_last_update_info()
165 def get_related_questions(self, count=10):
166 cache_key = '%s.related_questions:%d:%d' % (settings.APP_URL, count, self.id)
167 related_list = cache.get(cache_key)
169 if related_list is None:
170 related_list = Question.objects.values('id').filter(tags__id__in=[t.id for t in self.tags.all()]
171 ).exclude(id=self.id).exclude(deleted=True).annotate(frequency=models.Count('id')).order_by('-frequency')[:count]
172 cache.set(cache_key, related_list, 60 * 60)
174 return [Question.objects.get(id=r['id']) for r in related_list]
176 def __unicode__(self):
179 def question_viewed(instance, **kwargs):
180 instance.view_count += 1
183 question_view.connect(question_viewed)
185 class FavoriteQuestion(models.Model):
186 """A favorite Question of a User."""
187 question = models.ForeignKey('Question')
188 user = models.ForeignKey(User, related_name='user_favorite_questions')
189 added_at = models.DateTimeField(default=datetime.datetime.now)
192 unique_together = ('question', 'user')
194 db_table = u'favorite_question'
196 def __unicode__(self):
197 return '[%s] favorited at %s' %(self.user, self.added_at)
199 def _update_question_fav_count(self, diff):
200 self.question.favourite_count = self.question.favourite_count + diff
203 def save(self, *args, **kwargs):
204 super(FavoriteQuestion, self).save(*args, **kwargs)
206 self._update_question_fav_count(1)
209 self._update_question_fav_count(-1)
210 super(FavoriteQuestion, self).delete()
212 class QuestionSubscription(models.Model):
213 user = models.ForeignKey(User)
214 question = models.ForeignKey(Question)
215 auto_subscription = models.BooleanField(default=True)
216 last_view = models.DateTimeField(default=datetime.datetime.now())
221 class QuestionRevision(ContentRevision):
222 """A revision of a Question."""
223 question = models.ForeignKey(Question, related_name='revisions')
224 title = models.CharField(max_length=300)
225 tagnames = models.CharField(max_length=125)
227 class Meta(ContentRevision.Meta):
228 db_table = u'question_revision'
229 ordering = ('-revision',)
231 def get_question_title(self):
232 return self.question.title
234 def get_absolute_url(self):
235 #print 'in QuestionRevision.get_absolute_url()'
236 return reverse('question_revisions', args=[self.question.id])
238 def save(self, *args, **kwargs):
239 """Looks up the next available revision number."""
240 if not self.revision:
241 self.revision = QuestionRevision.objects.filter(
242 question=self.question).values_list('revision',
244 super(QuestionRevision, self).save(*args, **kwargs)
246 def __unicode__(self):
247 return u'revision %s of %s' % (self.revision, self.title)
249 class AnonymousQuestion(AnonymousContent):
250 title = models.CharField(max_length=300)
251 tagnames = models.CharField(max_length=125)
253 def publish(self,user):
254 added_at = datetime.datetime.now()
255 Question.objects.create_new(title=self.title, author=user, added_at=added_at,
256 wiki=self.wiki, tagnames=self.tagnames,
257 summary=self.summary, text=self.text)
260 from answer import Answer, AnswerManager