feat: Adds a language option to the update_translation_fields commands

Refs #563
Co-authored-by Fernando Cordeiro <fernando.cordeiro@jeronimo-martins.com>
This commit is contained in:
Fernando 2020-08-18 08:33:41 +01:00 committed by GitHub
parent 7a8a96ba18
commit ac91740a5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 6 deletions

View file

@ -23,10 +23,14 @@ command:
$ python manage.py update_translation_fields
Taken the news example used throughout the documentation this command will copy
the value from the news object's ``title`` field to the default translation
field ``title_de``. It only does so if the default translation field is empty
the value from the news object's ``title`` field to the translation
field ``title_de``. It only does so if the translation field is empty
otherwise nothing is copied.
On default, only the *default language* will have its translation field populated,
but you can provide a ``--language`` option to specify any other language listed
in ``settings.py``.
.. note::
Unless you configured modeltranslation to

View file

@ -1,14 +1,17 @@
# -*- coding: utf-8 -*-
from django.db.models import F, Q
from django.core.management.base import BaseCommand
from django.core.management.base import BaseCommand, CommandError
from modeltranslation.settings import DEFAULT_LANGUAGE
from modeltranslation.settings import AVAILABLE_LANGUAGES, DEFAULT_LANGUAGE
from modeltranslation.translator import translator
from modeltranslation.utils import build_localized_fieldname
COMMASPACE = ", "
class Command(BaseCommand):
help = ('Updates empty values of default translation fields using'
help = ('Updates empty values of translation fields using'
' values from original fields (in all translated models).')
def add_arguments(self, parser):
@ -20,6 +23,12 @@ class Command(BaseCommand):
'model_name', nargs='?',
help='Model name to update empty values of only this model.',
)
parser.add_argument(
'--language',
action='store',
help=('Language translation field the be updated.'
' Default language field if not provided')
)
def handle(self, *args, **options):
verbosity = options['verbosity']
@ -41,6 +50,17 @@ class Command(BaseCommand):
model_name = model_name.lower()
models = [m for m in models if m._meta.model_name == model_name]
# optionally defining the translation field language
lang = options.get('language') or DEFAULT_LANGUAGE
if lang not in AVAILABLE_LANGUAGES:
raise CommandError(
"Cannot find language '%s'. Options are %s." % (
lang, COMMASPACE.join(AVAILABLE_LANGUAGES)
)
)
else:
lang = lang.replace('-', '_')
if verbosity > 0:
self.stdout.write("Working on models: %s" % ', '.join([
"{app_label}.{object_name}".format(**m._meta.__dict__)
@ -53,7 +73,7 @@ class Command(BaseCommand):
opts = translator.get_options_for_model(model)
for field_name in opts.fields.keys():
def_lang_fieldname = build_localized_fieldname(field_name, DEFAULT_LANGUAGE)
def_lang_fieldname = build_localized_fieldname(field_name, lang)
# We'll only update fields which do not have an existing value
q = Q(**{def_lang_fieldname: None})

View file

@ -17,6 +17,7 @@ from django.core.exceptions import ValidationError, ImproperlyConfigured
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage
from django.core.management import call_command
from django.core.management.base import CommandError
from django.db import IntegrityError
from django.db.models import Q, F, Count, TextField
from django.test import TestCase, TransactionTestCase
@ -2024,6 +2025,24 @@ class UpdateCommandTest(ModeltranslationTestBase):
self.assertEqual('initial', obj1.title_de)
self.assertEqual('already', obj2.title_de)
def test_update_command_language_param(self):
trans_real.activate('en')
pk1 = models.TestModel.objects.create(title_en='').pk
pk2 = models.TestModel.objects.create(title_en='already').pk
# Due to ``rewrite(False)`` here, original field will be affected.
models.TestModel.objects.all().rewrite(False).update(title='initial')
call_command('update_translation_fields', language='en', verbosity=0)
obj1 = models.TestModel.objects.get(pk=pk1)
obj2 = models.TestModel.objects.get(pk=pk2)
self.assertEqual('initial', obj1.title_en)
self.assertEqual('already', obj2.title_en)
def test_update_command_invalid_language_param(self):
with self.assertRaises(CommandError):
call_command('update_translation_fields', language='xx', verbosity=0)
class TranslationAdminTest(ModeltranslationTestBase):
def setUp(self):