Add command to bulk move user language prefs from one code to another
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
"""
|
||||
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))
|
||||
Reference in New Issue
Block a user