Commit 6294baf4 by bmedx

Add command to bulk move user language prefs from one code to another

parent 98b391a2
"""
Migrates user preferences from one language code to another in batches. Dark lang preferences are not affected.
"""
from __future__ import print_function
import logging
from time import sleep
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.db.models import Q, Max
from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
from openedx.core.djangoapps.user_api.models import UserPreference
DEFAULT_CHUNK_SIZE = 10000
DEFAULT_SLEEP_TIME_SECS = 10
LOGGER = logging.getLogger(__name__)
class Command(BaseCommand):
"""
Implementation of the migrate command
"""
help = 'Migrate all user language preferences (excluding dark languages) from one language code to another.'
def add_arguments(self, parser):
parser.add_argument('old_lang_code',
help='Original language code, ex. "zh-cn"')
parser.add_argument('new_lang_code',
help='New language code, ex. "zh-hans"')
parser.add_argument('--start_id',
type=int,
default=1,
help='ID to begin from, in case a run needs to be restarted from the middle.')
parser.add_argument('--chunk_size',
type=int,
default=DEFAULT_CHUNK_SIZE,
help='Number of users whose preferences will be updated per batch.')
parser.add_argument('--sleep_time_secs',
type=int,
default=DEFAULT_SLEEP_TIME_SECS,
help='Number of seconds to sleep between batches.')
def handle(self, *args, **options):
"""
Execute the command.
"""
old_lang_code = options['old_lang_code']
new_lang_code = options['new_lang_code']
chunk_size = options['chunk_size']
sleep_time_secs = options['sleep_time_secs']
start = options['start_id']
end = start + chunk_size
# Make sure we're changing to a code that actually exists. Presumably it's safe to move away from a code that
# doesn't.
langs = [lang_code[0] for lang_code in settings.LANGUAGES]
langs += DarkLangConfig.current().released_languages_list
if new_lang_code not in langs:
raise CommandError('{} is not a configured language code in settings.LANGUAGES '
'or the current DarkLangConfig.'.format(new_lang_code))
max_id = UserPreference.objects.all().aggregate(Max('id'))['id__max']
print('Updating user language preferences from {} to {}. '
'Start id is {}, current max id is {}. '
'Chunk size is of {}'.format(old_lang_code, new_lang_code, start, max_id, chunk_size))
updated_count = 0
while True:
# On the last time through catch any new rows added since this run began
if end >= max_id:
print('Last round, includes all new rows added since this run started.')
id_query = Q(id__gte=start)
else:
id_query = Q(id__gte=start) & Q(id__lt=end)
curr = UserPreference.objects.filter(
id_query,
key='pref-lang',
value=old_lang_code
).update(value=new_lang_code)
updated_count += curr
print('Updated rows {} to {}, {} rows affected'.format(start, end - 1, curr))
if end >= max_id:
break
start = end
end += chunk_size
sleep(sleep_time_secs)
print('Finished! Updated {} total preferences from {} to {}'.format(updated_count, old_lang_code, new_lang_code))
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