summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askbot/migrations/0066_transplant_accepted_answer_data.py12
-rw-r--r--askbot/migrations/0092_postize_vote_and_activity.py53
-rw-r--r--askbot/migrations/0095_postize_award_and_repute.py13
-rw-r--r--askbot/models/post.py13
-rw-r--r--askbot/skins/default/templates/user_profile/user_stats.html6
-rw-r--r--askbot/tests/post_model_tests.py20
-rw-r--r--askbot/views/readers.py2
-rw-r--r--askbot/views/users.py24
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
))