diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2011-11-07 22:55:15 -0300 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2011-11-07 22:55:15 -0300 |
commit | 8d6ad91d93302194833ea187c465e5ac0c6795c5 (patch) | |
tree | 7add97c8fc118c59c6c6082f57e80807bbd75fe2 | |
parent | e4945502f2b079b9e53d1646800a7fcba1a0526a (diff) | |
parent | 761971c39e0ae517997868c582290076e969c4f2 (diff) | |
download | askbot-8d6ad91d93302194833ea187c465e5ac0c6795c5.tar.gz askbot-8d6ad91d93302194833ea187c465e5ac0c6795c5.tar.bz2 askbot-8d6ad91d93302194833ea187c465e5ac0c6795c5.zip |
Merge branch 'tomasz'
-rw-r--r-- | askbot/admin.py | 8 | ||||
-rw-r--r-- | askbot/management/commands/send_email_alerts.py | 8 | ||||
-rw-r--r-- | askbot/models/__init__.py | 6 | ||||
-rw-r--r-- | askbot/models/answer.py | 11 | ||||
-rw-r--r-- | askbot/models/base.py | 102 | ||||
-rw-r--r-- | askbot/models/post.py | 102 | ||||
-rw-r--r-- | askbot/models/question.py | 13 | ||||
-rw-r--r-- | askbot/views/users.py | 68 | ||||
-rw-r--r-- | askbot/views/writers.py | 4 |
9 files changed, 154 insertions, 168 deletions
diff --git a/askbot/admin.py b/askbot/admin.py index af62ed84..34722416 100644 --- a/askbot/admin.py +++ b/askbot/admin.py @@ -31,10 +31,7 @@ class VoteAdmin(admin.ModelAdmin): class FavoriteQuestionAdmin(admin.ModelAdmin): """ admin class""" -class QuestionRevisionAdmin(admin.ModelAdmin): - """ admin class""" - -class AnswerRevisionAdmin(admin.ModelAdmin): +class PostRevisionAdmin(admin.ModelAdmin): """ admin class""" class AwardAdmin(admin.ModelAdmin): @@ -52,8 +49,7 @@ admin.site.register(models.Answer, AnswerAdmin) admin.site.register(models.Comment, CommentAdmin) admin.site.register(models.Vote, VoteAdmin) admin.site.register(models.FavoriteQuestion, FavoriteQuestionAdmin) -admin.site.register(models.QuestionRevision, QuestionRevisionAdmin) -admin.site.register(models.AnswerRevision, AnswerRevisionAdmin) +admin.site.register(models.PostRevision, PostRevisionAdmin) admin.site.register(models.Award, AwardAdmin) admin.site.register(models.Repute, ReputeAdmin) admin.site.register(models.Activity, ActivityAdmin) diff --git a/askbot/management/commands/send_email_alerts.py b/askbot/management/commands/send_email_alerts.py index 330e1cc9..c904cdde 100644 --- a/askbot/management/commands/send_email_alerts.py +++ b/askbot/management/commands/send_email_alerts.py @@ -3,8 +3,8 @@ from django.core.management.base import NoArgsCommand from django.core.urlresolvers import reverse from django.db import connection from django.db.models import Q, F -from askbot.models import User, Question, Answer, Tag, QuestionRevision -from askbot.models import AnswerRevision, Activity, EmailFeedSetting +from askbot.models import User, Question, Answer, Tag, PostRevision +from askbot.models import Activity, EmailFeedSetting from askbot.models import Comment from askbot.models.question import get_tag_summary_from_questions from django.utils.translation import ugettext as _ @@ -336,7 +336,7 @@ class Command(NoArgsCommand): #collect info on all sorts of news that happened after #the most recent emailing to the user about this question - q_rev = QuestionRevision.objects.filter( + q_rev = PostRevision.objects.question_revisions().filter( question=q, revised_at__gt=emailed_at ) @@ -359,7 +359,7 @@ class Command(NoArgsCommand): new_ans = new_ans.exclude(author=user) meta_data['new_ans'] = len(new_ans) - ans_rev = AnswerRevision.objects.filter( + ans_rev = PostRevision.objects.answer_revisions().filter( answer__question = q, answer__deleted = False, revised_at__gt = emailed_at diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 6e23c8f3..807a29b7 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -19,10 +19,10 @@ import askbot from askbot import exceptions as askbot_exceptions from askbot import const from askbot.conf import settings as askbot_settings -from askbot.models.question import Question, QuestionRevision +from askbot.models.question import Question from askbot.models.question import QuestionView, AnonymousQuestion from askbot.models.question import FavoriteQuestion -from askbot.models.answer import Answer, AnonymousAnswer, AnswerRevision +from askbot.models.answer import Answer, AnonymousAnswer from askbot.models.tag import Tag, MarkedTag from askbot.models.meta import Vote, Comment from askbot.models.user import EmailFeedSetting, ActivityAuditStatus, Activity @@ -2644,13 +2644,11 @@ __all__ = [ 'signals', 'Question', - 'QuestionRevision', 'QuestionView', 'FavoriteQuestion', 'AnonymousQuestion', 'Answer', - 'AnswerRevision', 'AnonymousAnswer', 'PostRevision', diff --git a/askbot/models/answer.py b/askbot/models/answer.py index a694e737..cd9699ec 100644 --- a/askbot/models/answer.py +++ b/askbot/models/answer.py @@ -217,7 +217,7 @@ class Answer(content.Content, DeletableContent): comment = const.POST_STATUS['default_version'] else: comment = 'No.%s Revision' % rev_no - return AnswerRevision.objects.create( + return PostRevision.objects.create_answer_revision( answer=self, author=author, revised_at=revised_at, @@ -300,15 +300,6 @@ class Answer(content.Content, DeletableContent): return self.html -class AnswerRevision(PostRevision): - """A revision of an Answer.""" - - class Meta: - app_label = 'askbot' - proxy = True - - - class AnonymousAnswer(AnonymousContent): question = models.ForeignKey('Question', related_name='anonymous_answers') diff --git a/askbot/models/base.py b/askbot/models/base.py index b4492f0f..5ac2ac7a 100644 --- a/askbot/models/base.py +++ b/askbot/models/base.py @@ -1,18 +1,20 @@ import datetime import cgi -from django.core.urlresolvers import reverse +import logging + from django.db import models from django.utils.html import strip_tags from django.contrib.auth.models import User from django.contrib.contenttypes import generic from django.contrib.contenttypes.models import ContentType from django.contrib.sitemaps import ping_google + #todo: maybe merge askbot.utils.markup and forum.utils.html from askbot.utils import markup from askbot.utils.diff import textDiff as htmldiff from askbot.utils.html import sanitize_html from django.utils import html -import logging + #todo: following methods belong to a future common post class def parse_post_text(post): @@ -216,102 +218,6 @@ class DeletableContent(models.Model): app_label = 'askbot' -class ContentRevision(models.Model): - """ - Base class for QuestionRevision and AnswerRevision - """ - QUESTION_REVISION_TEMPLATE_NO_TAGS = ( - '<h3>%(title)s</h3>\n' - '<div class="text">%(html)s</div>\n' - ) - - QUESTION_REVISION = 1 - ANSWER_REVISION = 2 - REVISION_TYPE_CHOICES = ( - (QUESTION_REVISION, 'question'), - (ANSWER_REVISION, 'answer'), - ) - REVISION_TYPE_CHOICES_DICT = dict(REVISION_TYPE_CHOICES) - - revision_type = models.SmallIntegerField(choices=REVISION_TYPE_CHOICES) - - revision = models.PositiveIntegerField() - author = models.ForeignKey(User, related_name='%(class)ss') - revised_at = models.DateTimeField() - summary = models.CharField(max_length=300, blank=True) - text = models.TextField() - - # Question-specific fields - title = models.CharField(max_length=300, blank=True, default='') - tagnames = models.CharField(max_length=125, blank=True, default='') - is_anonymous = models.BooleanField(default=False) - - class Meta: - abstract = True - app_label = 'askbot' - ordering = ('-revision',) - - def revision_type_str(self): - return self.REVISION_TYPE_CHOICES_DICT[self.revision_type] - - def __unicode__(self): - return u'%s - revision %s of %s' % (self.revision_type_str(), self.revision, self.title) - - def parent(self): - if self.is_question_revision(): - return self.question - elif self.is_answer_revision(): - return self.answer - - def save(self, **kwargs): - """Determines the revistion type and then looks up the next available revision number if not set.""" - - if not self.revision_type: - # HACK: determine revision_type based on class name - until we have a better way or until make a switch to PostRevision - # After `revision_type` is set, we can just use it - if self.__class__.__name__ == 'QuestionRevision': - self.revision_type = self.QUESTION_REVISION - elif self.__class__.__name__ == 'AnswerRevision': - self.revision_type = self.ANSWER_REVISION - - if not self.revision: - # TODO: Maybe use Max() aggregation? - # TODO: Handle IntegrityError if revision id is already occupied? - self.revision = self.parent().revisions.values_list('revision', flat=True)[0] + 1 - - super(ContentRevision, self).save(**kwargs) - - def is_question_revision(self): - return self.revision_type == self.QUESTION_REVISION - - def is_answer_revision(self): - return self.revision_type == self.ANSWER_REVISION - - @models.permalink - def get_absolute_url(self): - if self.is_question_revision(): - return 'question_revisions', (self.question.id,), {} - elif self.is_answer_revision(): - return 'answer_revisions', (), {'id':self.answer.id} - - def get_question_title(self): - #INFO: ack-grepping shows that it's only used for Questions, so there's no code for Answers - return self.question.title - - def as_html(self, **kwargs): - markdowner = markup.get_parser() - sanitized_html = sanitize_html(markdowner.convert(self.text)) - - if self.is_question_revision(): - return self.QUESTION_REVISION_TEMPLATE_NO_TAGS % { - 'title': self.title, - 'html': sanitized_html - } - elif self.is_answer_revision(): - return sanitized_html - - - class AnonymousContent(models.Model): """ Base class for AnonymousQuestion and AnonymousAnswer diff --git a/askbot/models/post.py b/askbot/models/post.py index 17f0eb2c..c61e8877 100644 --- a/askbot/models/post.py +++ b/askbot/models/post.py @@ -1,14 +1,59 @@ from django.db import models -from askbot.models.base import ContentRevision +from askbot.utils import markup +from askbot.utils.html import sanitize_html #class Post(models.Model): # pass -class PostRevision(ContentRevision): +class PostRevisionManager(models.Manager): + def create_question_revision(self, *kargs, **kwargs): + kwargs['revision_type'] = self.model.QUESTION_REVISION + return self.create(*kargs, **kwargs) + + def create_answer_revision(self, *kargs, **kwargs): + kwargs['revision_type'] = self.model.ANSWER_REVISION + return self.create(*kargs, **kwargs) + + def question_revisions(self): + return self.filter(revision_type=self.model.QUESTION_REVISION) + + def answer_revisions(self): + return self.filter(revision_type=self.model.ANSWER_REVISION) + + +class PostRevision(models.Model): + QUESTION_REVISION_TEMPLATE_NO_TAGS = ( + '<h3>%(title)s</h3>\n' + '<div class="text">%(html)s</div>\n' + ) + + QUESTION_REVISION = 1 + ANSWER_REVISION = 2 + REVISION_TYPE_CHOICES = ( + (QUESTION_REVISION, 'question'), + (ANSWER_REVISION, 'answer'), + ) + REVISION_TYPE_CHOICES_DICT = dict(REVISION_TYPE_CHOICES) + answer = models.ForeignKey('askbot.Answer', related_name='revisions', null=True, blank=True) question = models.ForeignKey('askbot.Question', related_name='revisions', null=True, blank=True) + revision_type = models.SmallIntegerField(choices=REVISION_TYPE_CHOICES) + + revision = models.PositiveIntegerField() + author = models.ForeignKey('auth.User', related_name='%(class)ss') + revised_at = models.DateTimeField() + summary = models.CharField(max_length=300, blank=True) + text = models.TextField() + + # Question-specific fields + title = models.CharField(max_length=300, blank=True, default='') + tagnames = models.CharField(max_length=125, blank=True, default='') + is_anonymous = models.BooleanField(default=False) + + objects = PostRevisionManager() + class Meta: # INFO: This `unique_together` constraint might be problematic for databases in which # 2+ NULLs cannot be stored in an UNIQUE column. @@ -16,3 +61,56 @@ class PostRevision(ContentRevision): unique_together = (('answer', 'revision'), ('question', 'revision')) ordering = ('-revision',) app_label = 'askbot' + + def revision_type_str(self): + return self.REVISION_TYPE_CHOICES_DICT[self.revision_type] + + def __unicode__(self): + return u'%s - revision %s of %s' % (self.revision_type_str(), self.revision, self.title) + + def parent(self): + if self.is_question_revision(): + return self.question + elif self.is_answer_revision(): + return self.answer + + def save(self, **kwargs): + """Determines the revistion type and then looks up the next available revision number if not set.""" + + if not self.revision: + # TODO: Maybe use Max() aggregation? + # TODO: Handle IntegrityError if revision id is already occupied? + self.revision = self.parent().revisions.values_list('revision', flat=True)[0] + 1 + + self.full_clean() # Make sure that everything is ok, in particular that `revision_type` and `revision` are set to valid values + + super(PostRevision, self).save(**kwargs) + + def is_question_revision(self): + return self.revision_type == self.QUESTION_REVISION + + def is_answer_revision(self): + return self.revision_type == self.ANSWER_REVISION + + @models.permalink + def get_absolute_url(self): + if self.is_question_revision(): + return 'question_revisions', (self.question.id,), {} + elif self.is_answer_revision(): + return 'answer_revisions', (), {'id':self.answer.id} + + def get_question_title(self): + #INFO: ack-grepping shows that it's only used for Questions, so there's no code for Answers + return self.question.title + + def as_html(self, **kwargs): + markdowner = markup.get_parser() + sanitized_html = sanitize_html(markdowner.convert(self.text)) + + if self.is_question_revision(): + return self.QUESTION_REVISION_TEMPLATE_NO_TAGS % { + 'title': self.title, + 'html': sanitized_html + } + elif self.is_answer_revision(): + return sanitized_html diff --git a/askbot/models/question.py b/askbot/models/question.py index c2145f73..7f38bd5c 100644 --- a/askbot/models/question.py +++ b/askbot/models/question.py @@ -24,8 +24,6 @@ from askbot.models import signals from askbot import const from askbot.utils.lists import LazyList from askbot.utils.slug import slugify -from askbot.utils import markup -from askbot.utils.html import sanitize_html from askbot.utils import mysql #todo: too bad keys are duplicated see const sort methods @@ -760,7 +758,7 @@ class Question(content.Content, DeletableContent): # Create a new revision latest_revision = self.get_latest_revision() - QuestionRevision.objects.create( + PostRevision.objects.create_question_revision( question = self, title = latest_revision.title, author = retagged_by, @@ -838,7 +836,7 @@ class Question(content.Content, DeletableContent): else: comment = 'No.%s Revision' % rev_no - return QuestionRevision.objects.create( + return PostRevision.objects.create_question_revision( question = self, revision = rev_no, title = self.title, @@ -1007,13 +1005,6 @@ class FavoriteQuestion(models.Model): def __unicode__(self): return '[%s] favorited at %s' %(self.user, self.added_at) -class QuestionRevision(PostRevision): - """A revision of a Question.""" - - class Meta: - app_label = 'askbot' - proxy = True - class AnonymousQuestion(AnonymousContent): """question that was asked before logging in diff --git a/askbot/views/users.py b/askbot/views/users.py index f1f29f71..09acad07 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -38,27 +38,30 @@ from askbot.templatetags import extra_tags question_type = ContentType.objects.get_for_model(models.Question) answer_type = ContentType.objects.get_for_model(models.Answer) comment_type = ContentType.objects.get_for_model(models.Comment) -question_revision_type = ContentType.objects.get_for_model( - models.QuestionRevision - ) - -answer_revision_type = ContentType.objects.get_for_model( - models.AnswerRevision - ) +post_revision_type = ContentType.objects.get_for_model(models.PostRevision) repute_type = ContentType.objects.get_for_model(models.Repute) + question_type_id = question_type.id answer_type_id = answer_type.id comment_type_id = comment_type.id -question_revision_type_id = question_revision_type.id -answer_revision_type_id = answer_revision_type.id +post_revision_type_id = post_revision_type.id repute_type_id = repute_type.id #todo: queries in the user activity summary view must be redone -def get_related_object_type_name(content_type_id): - if content_type_id in (question_type_id, question_revision_type_id,): +def get_related_object_type_name(content_type_id, object_id): +# if content_type_id in (question_type_id, question_revision_type_id,): +# return 'question' +# elif content_type_id in (answer_type_id, answer_revision_type_id,): +# return 'answer' + + if content_type_id == question_type_id: return 'question' - elif content_type_id in (answer_type_id, answer_revision_type_id,): + elif content_type_id == answer_type_id: return 'answer' + elif content_type_id == post_revision_type_id: + post_revision = models.PostRevision.objects.get(id=object_id) + return post_revision.revision_type_str() + return None def owner_or_moderator_required(f): @@ -556,18 +559,20 @@ def user_recent(request, user, context): # question revisions revisions = models.Activity.objects.extra( select={ - 'title' : 'question_revision.title', - 'question_id' : 'question_revision.question_id', + 'title' : 'askbot_postrevision.title', + 'question_id' : 'askbot_postrevision.question_id', 'added_at' : 'activity.active_at', 'activity_type' : 'activity.activity_type', - 'summary' : 'question_revision.summary' + 'summary' : 'askbot_postrevision.summary' }, - tables=['activity', 'question_revision', 'question'], - where=['activity.content_type_id = %s AND activity.object_id = question_revision.id AND '+ - 'question_revision.id=question.id AND NOT question.deleted AND '+ - 'activity.user_id = question_revision.author_id AND activity.user_id = %s AND '+ - 'activity.activity_type=%s'], - params=[question_revision_type_id, user.id, const.TYPE_ACTIVITY_UPDATE_QUESTION], + tables=['activity', 'askbot_postrevision', 'question'], + where=[''' + activity.content_type_id=%s AND activity.object_id=askbot_postrevision.id AND + askbot_postrevision.question_id=question.id AND askbot_postrevision.revision_type=%s AND NOT question.deleted AND + activity.user_id=askbot_postrevision.author_id AND activity.user_id=%s AND + activity.activity_type=%s + '''], + params=[post_revision_type_id, models.PostRevision.QUESTION_REVISION, user.id, const.TYPE_ACTIVITY_UPDATE_QUESTION], order_by=['-activity.active_at'] ).values( 'title', @@ -590,16 +595,17 @@ def user_recent(request, user, context): 'answer_id' : 'answer.id', 'added_at' : 'activity.active_at', 'activity_type' : 'activity.activity_type', - 'summary' : 'answer_revision.summary' + 'summary' : 'askbot_postrevision.summary' }, - tables=['activity', 'answer_revision', 'question', 'answer'], - - where=['activity.content_type_id = %s AND activity.object_id = answer_revision.id AND '+ - 'activity.user_id = answer_revision.author_id AND activity.user_id = %s AND '+ - 'answer_revision.answer_id=answer.id AND answer.question_id = question.id AND '+ - 'NOT question.deleted AND NOT answer.deleted AND '+ - 'activity.activity_type=%s'], - params=[answer_revision_type_id, user.id, const.TYPE_ACTIVITY_UPDATE_ANSWER], + tables=['activity', 'askbot_postrevision', 'question', 'answer'], + where=[''' + activity.content_type_id=%s AND activity.object_id=askbot_postrevision.id AND + askbot_postrevision.answer_id=answer.id AND askbot_postrevision.revision_type=%s AND + answer.question_id=question.id AND NOT question.deleted AND NOT answer.deleted AND + activity.user_id=askbot_postrevision.author_id AND activity.user_id=%s AND + activity.activity_type=%s + '''], + params=[post_revision_type_id, models.PostRevision.ANSWER_REVISION, user.id, const.TYPE_ACTIVITY_UPDATE_ANSWER], order_by=['-activity.active_at'] ).values( 'title', @@ -662,7 +668,7 @@ def user_recent(request, user, context): 'activity_type' ) for award in awards: - related_object_type = get_related_object_type_name(award['content_type_id']) + related_object_type = get_related_object_type_name(content_type_id=award['content_type_id'], object_id=award['object_id']) activities.append( AwardEvent( award['awarded_at'], diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 8b07681a..b7b7e96d 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -363,7 +363,7 @@ def edit_question(request, id): if revision_form.is_valid(): # Replace with those from the selected revision rev_id = revision_form.cleaned_data['revision'] - selected_revision = models.QuestionRevision.objects.get( + selected_revision = models.PostRevision.objects.question_revisions().get( question = question, revision = rev_id ) @@ -448,7 +448,7 @@ def edit_answer(request, id): if revision_form.is_valid(): # Replace with those from the selected revision rev = revision_form.cleaned_data['revision'] - selected_revision = models.AnswerRevision.objects.get( + selected_revision = models.PostRevision.objects.answer_revisions().get( answer = answer, revision = rev ) |