diff --git a/wagtail_localize/fields.py b/wagtail_localize/fields.py index 9df48589..9c1aa11d 100644 --- a/wagtail_localize/fields.py +++ b/wagtail_localize/fields.py @@ -1,5 +1,5 @@ from django.db import models -from modelcluster.fields import ParentalKey +from modelcluster.fields import ParentalKey, ParentalManyToManyField from modelcluster.models import ClusterableModel, get_all_child_relations from treebeard.mp_tree import MP_Node from wagtail.fields import RichTextField, StreamField @@ -285,6 +285,13 @@ def copy_synchronised_fields(source, target): else: source.copy_child_relation(field.name, target) + elif isinstance(field, ParentalManyToManyField): + parental_field = getattr(source, field.name) + if hasattr(parental_field, "all"): + values = parental_field.all() + if values: + setattr(target, field.attname, values) + else: # For all other fields, just set the attribute setattr(target, field.attname, getattr(source, field.attname)) diff --git a/wagtail_localize/test/migrations/0004_testparentalsnippet.py b/wagtail_localize/test/migrations/0004_testparentalsnippet.py new file mode 100644 index 00000000..265a8f6d --- /dev/null +++ b/wagtail_localize/test/migrations/0004_testparentalsnippet.py @@ -0,0 +1,53 @@ +# Generated by Django 3.2.5 on 2022-05-06 18:53 + +from django.db import migrations, models +import django.db.models.deletion +import modelcluster.fields +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ("wagtail_localize_test", "0003_wagtail_3_use_json_field"), + ] + + operations = [ + migrations.CreateModel( + name="TestParentalSnippet", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "translation_key", + models.UUIDField(default=uuid.uuid4, editable=False), + ), + ( + "field", + modelcluster.fields.ParentalManyToManyField( + blank=True, to="wagtail_localize_test.TestUUIDModel" + ), + ), + ( + "locale", + models.ForeignKey( + editable=False, + on_delete=django.db.models.deletion.PROTECT, + related_name="+", + to="wagtailcore.locale", + ), + ), + ], + options={ + "abstract": False, + "unique_together": {("translation_key", "locale")}, + }, + ), + ] diff --git a/wagtail_localize/test/models.py b/wagtail_localize/test/models.py index 75d1dca3..8aa740cc 100644 --- a/wagtail_localize/test/models.py +++ b/wagtail_localize/test/models.py @@ -2,7 +2,7 @@ from django.db import models from django.utils.translation import gettext_lazy -from modelcluster.fields import ParentalKey +from modelcluster.fields import ParentalKey, ParentalManyToManyField from modelcluster.models import ClusterableModel from wagtail import blocks, telepath from wagtail.admin.panels import ( @@ -77,6 +77,16 @@ class TestUUIDSnippet(TranslatableMixin, models.Model): translatable_fields = [SynchronizedField("field")] +@register_snippet +class TestParentalSnippet(TranslatableMixin, ClusterableModel): + field = ParentalManyToManyField( + TestUUIDModel, + blank=True, + ) + + translatable_fields = [SynchronizedField("field")] + + @register_snippet class NonTranslatableSnippet(models.Model): field = models.TextField() diff --git a/wagtail_localize/tests/test_translation_model.py b/wagtail_localize/tests/test_translation_model.py index 201ed018..5bcc07a8 100644 --- a/wagtail_localize/tests/test_translation_model.py +++ b/wagtail_localize/tests/test_translation_model.py @@ -32,6 +32,7 @@ from wagtail_localize.strings import StringValue from wagtail_localize.test.models import ( TestPage, + TestParentalSnippet, TestSnippet, TestUUIDModel, TestUUIDSnippet, @@ -714,6 +715,22 @@ def test_uuid_snippet_save_target(self): translated_snippet = snippet.get_translation(self.fr_locale) self.assertEqual(translated_snippet.field.charfield, "Some Test") + def test_parental_many_to_many(self): + foreign_key_target = TestUUIDModel.objects.create(charfield="Some Test") + snippet = TestParentalSnippet.objects.create() + snippet.field = [foreign_key_target] + + source, created = TranslationSource.get_or_create_from_instance(snippet) + translation = Translation.objects.create( + source=source, + target_locale=self.fr_locale, + ) + + translation.save_target() + + translated_snippet = snippet.get_translation(self.fr_locale) + self.assertEqual(list(translated_snippet.field.all()), [foreign_key_target]) + @override_settings(WAGTAILLOCALIZE_DISABLE_ON_DELETE=True) class TestDeleteSourceDisablesTranslation(TestCase):