summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Zielinski <tomasz.zielinski@pyconsultant.eu>2011-11-25 22:36:32 +0100
committerTomasz Zielinski <tomasz.zielinski@pyconsultant.eu>2011-11-25 22:36:32 +0100
commit0eb019d50b0703c41d75afecb3fb5ede03628dd4 (patch)
tree97590776adf4635d8683752af689902f9d12b473
parent64e4e52dfc5bf00c85d88b78072739983fa04270 (diff)
downloadaskbot-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.py80
-rw-r--r--askbot/models/content.py112
-rw-r--r--askbot/models/question.py26
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()