From 4853ee2714c0aecf2e4779214253839044128660 Mon Sep 17 00:00:00 2001 From: Tomasz Zielinski Date: Fri, 6 Jan 2012 00:02:34 +0100 Subject: Upgraded migrations to fix a few small problems --- askbot/migrations/0090_postize_q_a_c.py | 12 +++- .../migrations/0092_postize_vote_and_activity.py | 67 ++++++++-------------- askbot/migrations/0095_postize_award_and_repute.py | 2 +- askbot/views/users.py | 1 + 4 files changed, 36 insertions(+), 46 deletions(-) diff --git a/askbot/migrations/0090_postize_q_a_c.py b/askbot/migrations/0090_postize_q_a_c.py index 42927d85..050028aa 100644 --- a/askbot/migrations/0090_postize_q_a_c.py +++ b/askbot/migrations/0090_postize_q_a_c.py @@ -9,6 +9,9 @@ class Migration(DataMigration): def forwards(self, orm): orm.Post.objects.all().delete() # in case there are some leftovers after this migration failed before + # TODO: start post.id from max(q.id, a.id, c.id) + store old_q_id, old_a_id, old_c_id inside - this is to make sure + # we can make old URLs work flawlessly + for q in orm.Question.objects.all(): orm.Post.objects.create( post_type='question', @@ -82,11 +85,11 @@ class Migration(DataMigration): # No need to investigate that as this is as simple as the "proper" way if (cm.content_type.app_label, cm.content_type.model) == ('askbot', 'question'): content_object = orm.Question.objects.get(id=cm.object_id) - thread = orm.Thread.objects.get(id=content_object.thread.id) # conver from Thread to orm.Thread - a subtle difference + thread = orm.Thread.objects.get(id=content_object.thread.id) # convert from Thread to orm.Thread - a subtle difference parent = orm.Post.objects.get(self_question=content_object) elif (cm.content_type.app_label, cm.content_type.model) == ('askbot', 'answer'): content_object = orm.Answer.objects.get(id=cm.object_id) - thread = orm.Thread.objects.get(id=content_object.question.thread.id) # conver from Thread to orm.Thread - a subtle difference + thread = orm.Thread.objects.get(id=content_object.question.thread.id) # convert from Thread to orm.Thread - a subtle difference parent = orm.Post.objects.get(self_answer=content_object) else: raise ValueError('comment.content_object is neither question nor answer!') @@ -124,6 +127,11 @@ class Migration(DataMigration): is_anonymous=False, ) + # Verify that numbers match + sum_all = orm.Question.objects.count() + orm.Answer.objects.count() + orm.Comment.objects.count() + if sum_all != orm.Post.objects.count(): + raise ValueError('sum(#Q,#C,#A) != #Post !') + def backwards(self, orm): "Write your backwards methods here." diff --git a/askbot/migrations/0092_postize_vote_and_activity.py b/askbot/migrations/0092_postize_vote_and_activity.py index e28bf441..e55df71e 100644 --- a/askbot/migrations/0092_postize_vote_and_activity.py +++ b/askbot/migrations/0092_postize_vote_and_activity.py @@ -7,16 +7,8 @@ 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') - - ### + # TODO: Speed this up by prefetching all votes ? 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) @@ -30,42 +22,26 @@ class Migration(DataMigration): ### - if not orm.Activity.objects.exists(): - return + # ContentType for Post model might not yet be present in the database + # (if migrations are applied in a row then contenttypes update is not called between them) + ct_post, c = orm['contenttypes.ContentType'].objects.get_or_create(app_label='askbot', model='post', defaults={'name': 'post'}) + + print "!!! [Red] Remember to not remove the old content types for Question, Answer and Comment models until all migrations succeed!" abandoned_activities = [] for a in orm.Activity.objects.all(): - save = False - content_tuple = (a.content_type.app_label, a.content_type.model) + # test if content_object for this activity exists - there might be a bunch of "abandoned" activities + model_signature = '.'.join([a.content_type.app_label, a.content_type.model]) + if not orm[model_signature].objects.filter(id=a.object_id).exists(): + abandoned_activities.append(a) + continue - 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 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 + save = False - 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 + model = a.content_type.model + if a.content_type.app_label == 'askbot' and model in ('question', 'answer', 'comment'): + a.object_id = orm.Post.objects.get(**{'self_%s__id' % model: a.object_id}).id save = True if a.question: @@ -76,10 +52,15 @@ class Migration(DataMigration): 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() + if abandoned_activities: + # Remove "abandoned" activities + abandoned_activities_lst = [ + (a.id, '.'.join([a.content_type.app_label, a.content_type.model]), a.object_id) + for a in abandoned_activities + ] + print "!!! Abandoned activities (num=%d):" % len(abandoned_activities), abandoned_activities_lst + for a in abandoned_activities: + a.delete() def backwards(self, orm): diff --git a/askbot/migrations/0095_postize_award_and_repute.py b/askbot/migrations/0095_postize_award_and_repute.py index bf6959ef..db18d0d7 100644 --- a/askbot/migrations/0095_postize_award_and_repute.py +++ b/askbot/migrations/0095_postize_award_and_repute.py @@ -8,7 +8,7 @@ from django.db import models class Migration(DataMigration): def forwards(self, orm): - if 'test' in sys.argv: # This migration fails when testing... Ah those: crappy Askbot test suite and broken Django test framework ;;-) + if 'test' in sys.argv: # This migration fails when running tests... return if orm.Award.objects.exists(): diff --git a/askbot/views/users.py b/askbot/views/users.py index 4a13d4a6..bcfbc28d 100644 --- a/askbot/views/users.py +++ b/askbot/views/users.py @@ -412,6 +412,7 @@ def user_recent(request, user, context): activities = [] + # TODO: Don't process all activities here for the user, only a subset ([:const.USER_VIEW_DATA_SIZE]) 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 -- cgit v1.2.3-1-g7c22