diff options
-rw-r--r-- | askbot/migrations/0066_transplant_accepted_answer_data.py | 12 | ||||
-rw-r--r-- | askbot/migrations/0092_postize_vote_and_activity.py | 53 | ||||
-rw-r--r-- | askbot/migrations/0095_postize_award_and_repute.py | 13 | ||||
-rw-r--r-- | askbot/models/post.py | 13 | ||||
-rw-r--r-- | askbot/skins/default/templates/user_profile/user_stats.html | 6 | ||||
-rw-r--r-- | askbot/tests/post_model_tests.py | 20 | ||||
-rw-r--r-- | askbot/views/readers.py | 2 | ||||
-rw-r--r-- | askbot/views/users.py | 24 |
8 files changed, 101 insertions, 42 deletions
diff --git a/askbot/migrations/0066_transplant_accepted_answer_data.py b/askbot/migrations/0066_transplant_accepted_answer_data.py index 91d66f76..6d1b7ca0 100644 --- a/askbot/migrations/0066_transplant_accepted_answer_data.py +++ b/askbot/migrations/0066_transplant_accepted_answer_data.py @@ -14,10 +14,14 @@ class Migration(DataMigration): try: accepted_answer = question.answers.get(accepted=True) # If this raises an error, we have a data integrity problem except orm.Answer.DoesNotExist, orm.Answer.MultipleObjectsReturned: - raise ValueError("There is a data integrity problem with some question/answers") - thread.accepted_answer = accepted_answer - thread.answer_accepted_at = accepted_answer.accepted_at - thread.save() + #raise ValueError("There is a data integrity problem with some question/answers") + # Unfortunately there's probably nothing we can do in this case, + # there's no record of which answer has been accepted (HMM, MAYBE IN ACTIVITIES???) + print "!!! Found a thread with question.answer_accepted, but no answer actually marked as accepted, question.id=%d" % question.id + else: + thread.accepted_answer = accepted_answer + thread.answer_accepted_at = accepted_answer.accepted_at + thread.save() # Verify data integrity for question in orm.Question.objects.all(): diff --git a/askbot/migrations/0092_postize_vote_and_activity.py b/askbot/migrations/0092_postize_vote_and_activity.py index d292330e..e28bf441 100644 --- a/askbot/migrations/0092_postize_vote_and_activity.py +++ b/askbot/migrations/0092_postize_vote_and_activity.py @@ -7,6 +7,16 @@ from django.db import models class Migration(DataMigration): def forwards(self, orm): + if orm.Activity.objects.exists(): + try: + ct_post = orm['contenttypes.ContentType'].objects.get(app_label='askbot', model='post') + except orm['contenttypes.ContentType'].DoesNotExist: + print "The new `Post` models doesn't yet have a matching ContentType instance," + print "but it'll be created by Django automatically, so just re-run ./manage.py migrate" + raise ValueError('Just re-run ./manage.py migrate') + + ### + for v in orm.Vote.objects.all(): if (v.content_type.app_label, v.content_type.model) == ('askbot', 'question'): v.voted_post = orm.Post.objects.get(self_question__id=v.object_id) @@ -20,17 +30,42 @@ class Migration(DataMigration): ### + if not orm.Activity.objects.exists(): + return + + abandoned_activities = [] + for a in orm.Activity.objects.all(): save = False + content_tuple = (a.content_type.app_label, a.content_type.model) - if (a.content_type.app_label, a.content_type.model) == ('askbot', 'question'): - a.content_object = orm.Post.objects.get(self_question__id=a.object_id) + if content_tuple == ('askbot', 'question'): + try: + orm.Question.objects.get(id=a.object_id) + except orm.Question.DoesNotExist: + # TODO: Maybe question can be recovered from activity.question denormalized field + # only only if activity.question is broken treat this activity as abandoned ? + abandoned_activities.append(a.id) + continue + a.object_id = orm.Post.objects.get(self_question__id=a.object_id).id save = True - elif (a.content_type.app_label, a.content_type.model) == ('askbot', 'answer'): - a.content_object = orm.Post.objects.get(self_answer__id=a.object_id) + + elif content_tuple == ('askbot', 'answer'): + try: + orm.Answer.objects.get(id=a.object_id) + except orm.Answer.DoesNotExist: + abandoned_activities.append(a.id) + continue + a.object_id = orm.Post.objects.get(self_answer__id=a.object_id).id save = True - elif (a.content_type.app_label, a.content_type.model) == ('askbot', 'comment'): - a.content_object = orm.Post.objects.get(self_comment__id=a.object_id) + + elif content_tuple == ('askbot', 'comment'): + try: + orm.Comment.objects.get(id=a.object_id) + except orm.Comment.DoesNotExist: + abandoned_activities.append(a.id) + continue + a.object_id = orm.Post.objects.get(self_comment__id=a.object_id).id save = True if a.question: @@ -38,8 +73,14 @@ class Migration(DataMigration): save = True if save: + a.content_type = ct_post a.save() + # INFO: non-batch delete to process all dependencies, if there are any + print "!!! Abandoned activities (num=%d):" % len(abandoned_activities), abandoned_activities + for a in orm.Activity.objects.filter(id__in=abandoned_activities): + a.delete() + def backwards(self, orm): "Write your backwards methods here." diff --git a/askbot/migrations/0095_postize_award_and_repute.py b/askbot/migrations/0095_postize_award_and_repute.py index be74d688..bf6959ef 100644 --- a/askbot/migrations/0095_postize_award_and_repute.py +++ b/askbot/migrations/0095_postize_award_and_repute.py @@ -25,16 +25,21 @@ class Migration(DataMigration): for aw in orm.Award.objects.all(): ct = aw.content_type - aw.content_type = ct_post + postize = False + if ct == ct_question: aw.object_id = orm.Post.objects.get(self_question__id=aw.object_id).id + postize = True elif ct == ct_answer: aw.object_id = orm.Post.objects.get(self_answer__id=aw.object_id).id + postize = True elif ct == ct_comment: aw.object_id = orm.Post.objects.get(self_comment__id=aw.object_id).id - else: - raise ValueError('Unknown award subject!') - aw.save() + postize = True + + if postize: + aw.content_type = ct_post + aw.save() ### diff --git a/askbot/models/post.py b/askbot/models/post.py index 1ee7b64e..715140c4 100644 --- a/askbot/models/post.py +++ b/askbot/models/post.py @@ -442,7 +442,6 @@ class Post(models.Model): class Meta: app_label = 'askbot' db_table = 'askbot_post' - ordering = ('-added_at',) # default ordering for comments, for other post types should be overriden per query def parse_post_text(post): @@ -472,7 +471,7 @@ class Post(models.Model): else: raise NotImplementedError - text = post.get_text() + text = post.text if _escape_html: text = cgi.escape(text) @@ -709,7 +708,7 @@ class Post(models.Model): otherwise, returns query set for all comments to a given post """ if visitor.is_anonymous(): - return self.comments.all().order_by('id') + return self.comments.order_by('added_at') else: upvoted_by_user = list(self.comments.filter(votes__user=visitor)) not_upvoted_by_user = list(self.comments.exclude(votes__user=visitor)) @@ -718,14 +717,10 @@ class Post(models.Model): c.upvoted_by_user = 1 # numeric value to maintain compatibility with previous version of this code comments = upvoted_by_user + not_upvoted_by_user - comments.sort(key=operator.attrgetter('id')) + comments.sort(key=operator.attrgetter('added_at')) return comments - #todo: maybe remove this wnen post models are unified - def get_text(self): - return self.text - def get_snippet(self): """returns an abbreviated snippet of the content """ @@ -1081,7 +1076,7 @@ class Post(models.Model): else: return self.added_at - def get_owner(self): + def get_owner(self): # TODO: remove me return self.author def get_author_list( diff --git a/askbot/skins/default/templates/user_profile/user_stats.html b/askbot/skins/default/templates/user_profile/user_stats.html index c16d63af..06e0e9a3 100644 --- a/askbot/skins/default/templates/user_profile/user_stats.html +++ b/askbot/skins/default/templates/user_profile/user_stats.html @@ -13,13 +13,13 @@ {% include "user_profile/users_questions.html" %} <a name="answers"></a> {% spaceless %} - <h2 style="clear:both;"><span class="count">{{counter}}</span> {% trans counter=top_answer_count %}Answer{% pluralize %}Answers{% endtrans %}</h2> + <h2 style="clear:both;"><span class="count">{{ top_answer_count }}</span> {% trans counter=top_answer_count %}Answer{% pluralize %}Answers{% endtrans %}</h2> {% endspaceless %} <div class="user-stats-table"> {% for top_answer in top_answers %} <div class="answer-summary"> <a title="{{ top_answer.summary|collapse }}" - href="{% url question top_answer.question_id %}{{ top_answer.thread.title|slugify }}#{{ top_answer.id }}"> + href="{% url question top_answer.thread._question_post().id %}{{ top_answer.thread.title|slugify }}#{{ top_answer.id }}"> <span class="answer-votes {% if top_answer.is_answer_accepted() %}answered-accepted{% endif %}" title="{% trans answer_score=top_answer.score %}the answer has been voted for {{ answer_score }} times{% endtrans %} {% if top_answer.is_answer_accepted() %}{% trans %}this answer has been selected as correct{% endtrans %}{%endif%}"> {{ top_answer.score }} @@ -27,7 +27,7 @@ </a> <div class="answer-link"> {% spaceless %} - <a href="{% url question top_answer.question_id %}{{ top_answer.thread.title|slugify }}#{{top_answer.id}}">{{ top_answer.thread.title }}</a> + <a href="{% url question top_answer.thread._question_post().id %}{{ top_answer.thread.title|slugify }}#{{top_answer.id}}">{{ top_answer.thread.title }}</a> {% endspaceless %} {% if top_answer.comment_count > 0 %} <span> diff --git a/askbot/tests/post_model_tests.py b/askbot/tests/post_model_tests.py index cf03916c..03d4023c 100644 --- a/askbot/tests/post_model_tests.py +++ b/askbot/tests/post_model_tests.py @@ -106,3 +106,23 @@ class PostModelTests(AskbotTestCase): question.apply_edit(edited_by=self.u1, text="blah3", comment="blahc3") self.assertEqual(3, question.revisions.all()[0].revision) self.assertEqual(3, question.revisions.count()) + + def test_comment_ordering_by_date(self): + self.user = self.u1 + q = self.post_question() + + c1 = self.post_comment(parent_post=q) + c2 = q.add_comment(user=self.user, comment='blah blah') + c3 = self.post_comment(parent_post=q) + + self.assertListEqual([c1, c2, c3], q.get_comments(visitor=self.user)) + self.assertListEqual([c1, c2, c3], q.get_comments(visitor=self.u2)) + + c1.added_at, c3.added_at = c3.added_at, c1.added_at + c1.save() + c3.save() + + self.assertListEqual([c3, c2, c1], q.get_comments(visitor=self.user)) + self.assertListEqual([c3, c2, c1], q.get_comments(visitor=self.u2)) + + del self.user
\ No newline at end of file diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 8931260b..b14e1551 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -425,7 +425,7 @@ def question(request, id):#refactor - long subroutine. display question body, an #load question and maybe refuse showing deleted question try: - question_post = get_object_or_404(models.Post, id=id) + question_post = get_object_or_404(models.Post, post_type='question', id=id) question_post.assert_is_visible_to(request.user) except exceptions.QuestionHidden, error: request.user.message_set.create(message = unicode(error)) diff --git a/askbot/views/users.py b/askbot/views/users.py index 1c575744..6bf39f35 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -287,12 +287,11 @@ def user_stats(request, user, context): # # Top answers # -# TODO: Rewrite this without using `self_answer` -# top_answers = user.posts.get_answers().filter( -# deleted=False, -# self_answer__question__deleted=False, -# ).select_related('thread', 'self_answer').order_by('-score', '-id')[:100] - top_answers = [] + top_answers = user.posts.get_answers().filter( + deleted=False, + thread__posts__deleted=False, + thread__posts__post_type='question', + ).select_related('thread').order_by('-score', '-added_at')[:100] top_answer_count = len(top_answers) @@ -327,15 +326,12 @@ def user_stats(request, user, context): if award.content_type_id == post_type.id: awarded_post_ids.append(award.object_id) - awarded_posts = models.Post.objects.filter( - Q(post_type='answer')|Q(post_type='question'), - id__in=awarded_post_ids, - ).select_related('thread') # select related to avoid additional queries in Post.get_absolute_url() + awarded_posts = models.Post.objects.filter(id__in=awarded_post_ids)\ + .select_related('thread') # select related to avoid additional queries in Post.get_absolute_url() awarded_posts_map = {} for post in awarded_posts: - if post.post_type in ('question', 'answer'): - awarded_posts_map[post.id] = post + awarded_posts_map[post.id] = post badges_dict = collections.defaultdict(list) @@ -415,8 +411,6 @@ def user_recent(request, user, context): activities = [] - # TODO: Convert to Post - for activity in models.Activity.objects.filter(user=user): # TODO: multi-if means that we have here a construct for which a design pattern should be used @@ -429,7 +423,7 @@ def user_recent(request, user, context): time=activity.active_at, type=activity.activity_type, title=q.thread.title, - summary=q.summary, # TODO: was set to '' before, but that was probably wrong + summary='', #q.summary, # TODO: was set to '' before, but that was probably wrong answer_id=0, question_id=q.id )) |