Commit 34633365 by J. Cliff Dyer Committed by J. Cliff Dyer

New course key migration script.

parent e502a556
...@@ -11,7 +11,7 @@ dependencies: ...@@ -11,7 +11,7 @@ dependencies:
- "pip install -r requirements.txt" - "pip install -r requirements.txt"
- "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/base.txt" - "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/base.txt"
- "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/test.txt" - "pip install -r $VIRTUAL_ENV/src/xblock-sdk/requirements/test.txt"
- "pip uninstall -y xblock-problem-builder && python setup.py sdist && pip install dist/xblock-problem-builder-2.6.5.tar.gz" - "pip uninstall -y xblock-problem-builder && python setup.py sdist && pip install dist/xblock-problem-builder-2.6.5.patch1.tar.gz"
- "pip install -r test_requirements.txt" - "pip install -r test_requirements.txt"
- "mkdir var" - "mkdir var"
test: test:
......
"""
Command to copy content of Answer.course_id to Answer.course_key.
"""
import time
from django.core.management.base import BaseCommand
from django.db.models import F, Q
from problem_builder.models import Answer
class Command(BaseCommand):
"""
Copy content of the deprecated Answer.course_id column into
Answer.course_key in batches. The batch size and sleep time between
batches are configurable.
"""
help = 'Copy content of the deprecated Answer.course_id column to Answer.course_key in batches'
def add_arguments(self, parser):
parser.add_argument(
'--batch-size',
help='The size of each batch of records to copy (default: 5000).',
type=int,
default=5000,
)
parser.add_argument(
'--offset',
help='The lowest primary key to copy (default: 0)',
type=int,
default=0,
)
parser.add_argument(
'--sleep',
help='Number of seconds to sleep before processing the next batch (default: 1).',
type=int,
default=1,
)
def handle(self, *args, **options):
batch_size = options['batch_size']
sleep_time = options['sleep']
offset = options['offset']
max_pk = Answer.objects.order_by('-pk')[0].pk
batch_start = offset
batch_stop = batch_start + batch_size
self.stdout.write(
"Copying Answer.course_id field into Answer.course_key in batches of at most {}".format(
batch_size
)
)
while batch_start <= max_pk:
queryset = Answer.objects.filter(
pk__gte=batch_start,
pk__lt=batch_stop,
).filter(
Q(course_key__isnull=True) | Q(course_key='')
)
queryset.update(course_key=F('course_id'))
self.stdout.write(
"Processed Answers through pk: {}, max pk: {}".format(batch_stop, max_pk)
)
if batch_stop < max_pk:
time.sleep(sleep_time)
batch_start = batch_stop
batch_stop += batch_size
self.stdout.write("Successfully copied Answer.course_id into Answer.course_key")
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
def copy_course_id_to_course_key(apps, schema_editor):
"""
Iterates over all Answer records for which course_key is not set
and copies the value of the course_id column into course_key.
"""
Answer = apps.get_model('problem_builder', 'Answer')
for answer in Answer.objects.filter(course_key__isnull=True).iterator():
answer.course_key = answer.course_id
answer.save()
class Migration(migrations.Migration):
dependencies = [
('problem_builder', '0003_auto_20161124_0755'),
]
operations = [
migrations.RunPython(code=migrations.RunPython.noop, reverse_code=migrations.RunPython.noop),
]
"""
Tests of the management command to copy Answer.course_id to Answer.course_key.
"""
from django.test import TestCase
from opaque_keys.edx.keys import CourseKey
from problem_builder.management.commands.problem_builder_migrate_keys import Command
from problem_builder.models import Answer
class TestProblemBuilderMigrateKeysCommand(TestCase):
"""
Management command unit tests.
"""
def setUp(self):
for i in xrange(12):
Answer.objects.create(
course_id=CourseKey.from_string('course-v1:Org+Course+{}'.format(i)),
course_key=None,
)
def test_command(self):
cmd = Command()
cmd.handle(batch_size=3, sleep=0)
for answer in Answer.objects.all():
self.assertEqual(answer.course_key, answer.course_id)
def test_existing_course_key(self):
cmd = Command()
answer = Answer.objects.get(course_id__endswith='+0')
answer.course_key = CourseKey.from_string('course-v1:This+is+different')
answer.save()
cmd.handle(batch_size=3, sleep=0)
answer.refresh_from_db()
self.assertNotEqual(answer.course_key, answer.course_id)
ddt ddt
mock mock
unicodecsv==0.9.4 unicodecsv==0.9.4
edx-opaque-keys>=0.4
-e git+https://github.com/edx/xblock-utils.git@v1.0.3#egg=xblock-utils -e git+https://github.com/edx/xblock-utils.git@v1.0.3#egg=xblock-utils
-e . -e .
...@@ -71,9 +71,9 @@ BLOCKS = [ ...@@ -71,9 +71,9 @@ BLOCKS = [
setup( setup(
name='xblock-problem-builder', name='xblock-problem-builder',
version='2.6.5', version='2.6.5patch1',
description='XBlock - Problem Builder', description='XBlock - Problem Builder',
packages=['problem_builder', 'problem_builder.v1'], packages=['problem_builder', 'problem_builder.v1', 'problem_builder.management', 'problem_builder.management.commands'],
install_requires=[ install_requires=[
'XBlock', 'XBlock',
'xblock-utils', 'xblock-utils',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment