diff options
author | Tomasz Zielinski <tomasz.zielinski@pyconsultant.eu> | 2011-11-25 22:36:32 +0100 |
---|---|---|
committer | Tomasz Zielinski <tomasz.zielinski@pyconsultant.eu> | 2011-11-25 22:36:32 +0100 |
commit | 0eb019d50b0703c41d75afecb3fb5ede03628dd4 (patch) | |
tree | 97590776adf4635d8683752af689902f9d12b473 | |
parent | 64e4e52dfc5bf00c85d88b78072739983fa04270 (diff) | |
download | askbot-0eb019d50b0703c41d75afecb3fb5ede03628dd4.tar.gz askbot-0eb019d50b0703c41d75afecb3fb5ede03628dd4.tar.bz2 askbot-0eb019d50b0703c41d75afecb3fb5ede03628dd4.zip |
Initial extraction of Question&Answer model methods to their common parent class Content
-rw-r--r-- | askbot/models/answer.py | 80 | ||||
-rw-r--r-- | askbot/models/content.py | 112 | ||||
-rw-r--r-- | askbot/models/question.py | 26 |
3 files changed, 114 insertions, 104 deletions
diff --git a/askbot/models/answer.py b/askbot/models/answer.py index cd9699ec..35701ff1 100644 --- a/askbot/models/answer.py +++ b/askbot/models/answer.py @@ -81,7 +81,7 @@ class AnswerManager(models.Manager): # cursor.execute(self.GET_ANSWERS_FROM_USER_QUESTIONS, [user_id, user_id]) # return cursor.fetchall() -class Answer(content.Content, DeletableContent): +class Answer(content.Content): post_type = 'answer' question = models.ForeignKey('Question', related_name='answers') accepted = models.BooleanField(default=False) @@ -92,8 +92,6 @@ class Answer(content.Content, DeletableContent): class Meta(content.Content.Meta): db_table = u'answer' - parse = parse_post_text - parse_and_save = parse_and_save_post is_anonymous = False #answers are never anonymous - may change def assert_is_visible_to(self, user): @@ -161,51 +159,6 @@ class Answer(content.Content, DeletableContent): self.question.last_activity_by = edited_by self.question.save() - def repost_as_question(self, new_title = None): - """posts answer as question, together with all the comments - while preserving time stamps and authors - does not delete the answer itself though - """ - revisions = self.revisions.all().order_by('revised_at') - rev0 = revisions[0] - new_question = rev0.author.post_question( - title = new_title, - body_text = rev0.text, - tags = self.question.tagnames, - wiki = self.question.wiki, - is_anonymous = self.question.is_anonymous, - timestamp = rev0.revised_at - ) - if len(revisions) > 1: - for rev in revisions[1:]: - rev.author.edit_question( - question = new_question, - body_text = rev.text, - revision_comment = rev.summary, - timestamp = rev.revised_at - ) - for comment in self.comments.all(): - comment.content_object = new_question - comment.save() - return new_question - - def swap_with_question(self, new_title = None): - """swaps answer with the question it belongs to and - sets the title of question to ``new_title`` - """ - #1) make new question by using new title, tags of old question - # and the answer body, as well as the authors of all revisions - # and repost all the comments - new_question = self.repost_as_question(new_title = new_title) - - #2) post question (all revisions and comments) as answer - new_answer = self.question.repost_as_answer(question = new_question) - - #3) assign all remaining answers to the new question - self.question.answers.update(question = new_question) - self.question.delete() - self.delete() - return new_question def add_revision(self, author=None, revised_at=None, text=None, comment=None): #todo: this may be identical to Question.add_revision @@ -226,27 +179,6 @@ class Answer(content.Content, DeletableContent): revision=rev_no ) - def save(self, *args, **kwargs): - super(Answer, self).save(*args, **kwargs); - if 'postgres' in settings.DATABASE_ENGINE: - #hit the database to trigger update of full text search vector - self.question.save() - - def get_origin_post(self): - return self.question - - def get_page_number(self, answers = None): - """When question has many answers, answers are - paginated. This function returns number of the page - on which the answer will be shown, using the default - sort order. The result may depend on the visitor.""" - order_number = 0 - for answer in answers: - if self == answer: - break - order_number += 1 - return int(order_number/const.ANSWERS_PAGE_SIZE) + 1 - def get_response_receivers(self, exclude_list = None): """get list of users interested in this response update based on their participation in the question @@ -275,16 +207,6 @@ class Answer(content.Content, DeletableContent): return list(recipients) - def get_user_vote(self, user): - if user.is_anonymous(): - return None - - votes = self.votes.filter(user=user) - if votes and votes.count() > 0: - return votes[0] - else: - return None - def get_question_title(self): return self.question.title diff --git a/askbot/models/content.py b/askbot/models/content.py index c1760593..56c7b6aa 100644 --- a/askbot/models/content.py +++ b/askbot/models/content.py @@ -1,4 +1,5 @@ import datetime +from django.conf import settings from django.contrib.auth.models import User from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType @@ -9,6 +10,7 @@ from askbot import const from askbot.models.meta import Comment, Vote from askbot.models.user import EmailFeedSetting from askbot.models.tag import Tag, MarkedTag, tags_match_some_wildcard +from askbot.models.base import parse_post_text, parse_and_save_post from askbot.conf import settings as askbot_settings class Content(models.Model): @@ -18,6 +20,10 @@ class Content(models.Model): author = models.ForeignKey(User, related_name='%(class)ss') added_at = models.DateTimeField(default=datetime.datetime.now) + deleted = models.BooleanField(default=False) + deleted_at = models.DateTimeField(null=True, blank=True) + deleted_by = models.ForeignKey(User, null=True, blank=True, related_name='deleted_%(class)ss') + wiki = models.BooleanField(default=False) wikified_at = models.DateTimeField(null=True, blank=True) @@ -48,6 +54,22 @@ class Content(models.Model): abstract = True app_label = 'askbot' + parse = parse_post_text + parse_and_save = parse_and_save_post + + def is_answer(self): + return self.post_type == 'answer' + + def is_question(self): + return self.post_type == 'question' + + def save(self, *args, **kwargs): + models.Model.save(self, *args, **kwargs) # TODO: figure out how to use super() here + if self.is_answer() and 'postgres' in settings.DATABASE_ENGINE: + #hit the database to trigger update of full text search vector + self.question.save() + + def get_comments(self, visitor = None): """returns comments for a post, annotated with ``upvoted_by_user`` parameter, if visitor is logged in @@ -396,3 +418,93 @@ class Content(models.Model): when = c.added_at who = c.user return when, who + + def tagname_meta_generator(self): + return u','.join([unicode(tag) for tag in self.get_tag_names()]) + + def get_origin_post(self): + if self.is_answer(): + return self.question + elif self.is_question(): + return self + raise NotImplementedError + + def _repost_as_question(self, new_title = None): + """posts answer as question, together with all the comments + while preserving time stamps and authors + does not delete the answer itself though + """ + if not self.is_answer(): + raise NotImplementedError + revisions = self.revisions.all().order_by('revised_at') + rev0 = revisions[0] + new_question = rev0.author.post_question( + title = new_title, + body_text = rev0.text, + tags = self.question.tagnames, + wiki = self.question.wiki, + is_anonymous = self.question.is_anonymous, + timestamp = rev0.revised_at + ) + if len(revisions) > 1: + for rev in revisions[1:]: + rev.author.edit_question( + question = new_question, + body_text = rev.text, + revision_comment = rev.summary, + timestamp = rev.revised_at + ) + for comment in self.comments.all(): + comment.content_object = new_question + comment.save() + return new_question + + def swap_with_question(self, new_title = None): + """swaps answer with the question it belongs to and + sets the title of question to ``new_title`` + """ + if not self.is_answer(): + raise NotImplementedError + #1) make new question by using new title, tags of old question + # and the answer body, as well as the authors of all revisions + # and repost all the comments + new_question = self._repost_as_question(new_title = new_title) + + #2) post question (all revisions and comments) as answer + new_answer = self.question.repost_as_answer(question = new_question) + + #3) assign all remaining answers to the new question + self.question.answers.update(question = new_question) + self.question.delete() + self.delete() + return new_question + + + def get_page_number(self, answers = None): + """When question has many answers, answers are + paginated. This function returns number of the page + on which the answer will be shown, using the default + sort order. The result may depend on the visitor.""" + if self.is_question(): + return 1 + elif self.is_answer(): + order_number = 0 + for answer in answers: + if self == answer: + break + order_number += 1 + return int(order_number/const.ANSWERS_PAGE_SIZE) + 1 + raise NotImplementedError + + def get_user_vote(self, user): + if not self.is_answer(): + raise NotImplementedError + + if user.is_anonymous(): + return None + + votes = self.votes.filter(user=user) + if votes and votes.count() > 0: + return votes[0] + else: + return None diff --git a/askbot/models/question.py b/askbot/models/question.py index c2d4be11..3f3e62c1 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -450,7 +450,7 @@ class QuestionManager(BaseQuerySetManager): return QuestionQuerySet(self.model) -class Question(content.Content, DeletableContent): +class Question(content.Content): post_type = 'question' title = models.CharField(max_length=300) tags = models.ManyToManyField('Tag', related_name='questions') @@ -482,9 +482,6 @@ class Question(content.Content, DeletableContent): class Meta(content.Content.Meta): db_table = u'question' - parse = parse_post_text - parse_and_save = parse_and_save_post - def assert_is_visible_to(self, user): """raises QuestionHidden""" if self.deleted: @@ -564,13 +561,6 @@ class Question(content.Content, DeletableContent): return LazyList(get_data) - def get_page_number(self, answers = None): - """question always appears on its own - first page by definition. The answers - parameter is not used here. The extra parameter is necessary - to maintain generality of the function call signature""" - return 1 - def get_similarity(self, other_question = None): """return number of tags in the other question that overlap with the current question (self) @@ -768,9 +758,6 @@ class Question(content.Content, DeletableContent): text = latest_revision.text ) - def get_origin_post(self): - return self - def apply_edit(self, edited_at=None, edited_by=None, title=None,\ text=None, comment=None, tags=None, wiki=False, \ edit_anonymously = False): @@ -859,9 +846,6 @@ class Question(content.Content, DeletableContent): """ self.tagnames = u' '.join(tag_names) - def tagname_meta_generator(self): - return u','.join([unicode(tag) for tag in self.get_tag_names()]) - def get_absolute_url(self, no_slug = False): url = reverse('question', args=[self.id]) if no_slug == True: @@ -880,11 +864,6 @@ class Question(content.Content, DeletableContent): return FavoriteQuestion.objects.filter(question=self, user=user).count() > 0 - def get_answer_count_by_user(self, user_id): - from askbot.models.answer import Answer - query_set = Answer.objects.filter(author__id=user_id) - return query_set.filter(question=self).count() - def get_question_title(self): if self.closed: attr = const.POST_STATUS['closed'] @@ -897,9 +876,6 @@ class Question(content.Content, DeletableContent): else: return self.title - def get_revision_url(self): - return reverse('question_revisions', args=[self.id]) - def get_last_update_info(self): when, who = self.post_get_last_update_info() |