def test_field_gets_original_validators(self): def validator(value): if value in (None, ""): return if int(value) < 20: raise ValidationError("must be equal to or greater than 20.") class TestModel5(models.Model): title = models.CharField(max_length=100, validators=[validator]) i18n = TranslationField(fields=("title", )) class Meta: app_label = "django-modeltrans_tests" translate_model(TestModel5) field = TestModel5._meta.get_field("title") self.assertTrue(validator in field.validators) field = TestModel5._meta.get_field("title_nl") self.assertTrue(validator in field.validators) m = TestModel5(title="22", title_nl="10") with self.assertRaises(ValidationError) as e: m.full_clean() self.assertEqual( list(e.exception), [("title_nl", ["must be equal to or greater than 20."])])
def test_meta_ordering(self): """ This needs expressions in Model.Meta.ordering, added in django 2.0 https://github.com/django/django/pull/8673 """ class MetaOrderingModel(models.Model): # doesn't make sense to translate names, but it serves as a test. first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) i18n = TranslationField(fields=("last_name", "first_name")) class Meta: ordering = ("last_name_i18n", "first_name_i18n") app_label = "tests" TEST_NAMES = ( ("Jaïr", "Kleinsma"), ("Hakki", "van Velsen"), ("Josip", "Engel"), ("Berry", "Reuver"), ) translate_model(MetaOrderingModel) with CreateTestModel(MetaOrderingModel): for first, last in TEST_NAMES: MetaOrderingModel.objects.create(first_name=first, last_name=last) qs = MetaOrderingModel.objects.all() self.assertEqual(key(qs, "first_name"), "Josip Jaïr Berry Hakki") # overridden: self.assertEqual(key(qs.order_by("first_name"), "first_name"), "Berry Hakki Jaïr Josip")
def test_translate_model_with_custom_manager(self): """ Verify the MultiLingualManager gets mixed in properly """ class CustomQuerySet(models.query.QuerySet): pass class CustomManager(models.Manager): def get_queryset(self): return CustomQuerySet() def custom_method(self): return "foo" class TestModel1(models.Model): name = models.CharField(max_length=100) i18n = TranslationField(fields=("name", )) objects = CustomManager() class Meta: app_label = "django-modeltrans_tests" translate_model(TestModel1) self.assertIsInstance(TestModel1.objects, CustomManager) self.assertIsInstance(TestModel1.objects, MultilingualManager) self.assertEqual(TestModel1.objects.custom_method(), "foo") self.assertIsInstance(TestModel1.objects.all(), MultilingualQuerySet)
def test_field_gets_original_validators(self): def validator(value): if value in (None, ''): return if int(value) < 20: raise ValidationError('must be equal to or greater than 20.') class TestModel5(models.Model): title = models.CharField(max_length=100, validators=[ validator, ]) i18n = TranslationField(fields=('title', )) class Meta: app_label = 'django-modeltrans_tests' translate_model(TestModel5) field = TestModel5._meta.get_field('title') self.assertTrue(validator in field.validators) field = TestModel5._meta.get_field('title_nl') self.assertTrue(validator in field.validators) m = TestModel5(title='22', title_nl='10') with self.assertRaises(ValidationError) as e: m.full_clean() self.assertEquals(list(e.exception), [ ('title_nl', ['must be equal to or greater than 20.']), ])
def test_translate_model_with_non_modeltrans_i18n_field(self): class TestModel3(models.Model): title = models.CharField(max_length=100) i18n = models.BooleanField() class Meta: app_label = "django-modeltrans_tests" translate_model(TestModel3)
def test_translate_bad_required_languages_type(self): class BadRequiredLanguagesType(models.Model): title = models.CharField(max_length=100) i18n = TranslationField(fields=("title",), required_languages=("es")) class Meta: app_label = "django-modeltrans_tests" expected_message = '"required_languages" must be a tuple, list, set or dict' with self.assertRaisesMessage(ImproperlyConfigured, expected_message): translate_model(BadRequiredLanguagesType)
def test_translation_unsupported_field(self): class IntegerModel(models.Model): integer = models.IntegerField() i18n = TranslationField(fields=("integer", )) class Meta: app_label = "django-modeltrans_tests" expected_message = "IntegerField is not supported by django-modeltrans." with self.assertRaisesMessage(ImproperlyConfigured, expected_message): translate_model(IntegerModel)
def test_translate_nonexisting_field(self): class B(models.Model): i18n = TranslationField(fields=("foo", )) class Meta: app_label = "django-modeltrans_tests" expected_message = ( 'Argument "fields" to TranslationField contains an item "foo", ' "which is not a field (missing a comma?).") with self.assertRaisesMessage(ImproperlyConfigured, expected_message): translate_model(B)
def test_translate_required_languages_dict(self): class RequiredLanguagesType_dict(models.Model): title = models.CharField(max_length=100) body = models.CharField(max_length=100) i18n = TranslationField( fields=("title", "body"), required_languages={"body": ["nl"], "title": ["fr", "nl"]} ) class Meta: app_label = "django-modeltrans_tests" translate_model(RequiredLanguagesType_dict)
def test_translate_required_languages_dict_bad_value(self): class BadRequiredLanguagesType_dict(models.Model): title = models.CharField(max_length=100) body = models.CharField(max_length=100) i18n = TranslationField( fields=("title", "body"), required_languages={"body": ["nl"], "title": "es"} ) class Meta: app_label = "django-modeltrans_tests" expected_message = 'required_languages["title"] must be a tuple, list or set' with self.assertRaisesMessage(ImproperlyConfigured, expected_message): translate_model(BadRequiredLanguagesType_dict)
def test_translate_bad_required_language(self): class A(models.Model): title = models.CharField(max_length=100) i18n = TranslationField(fields=("title", ), required_languages=("es", )) class Meta: app_label = "django-modeltrans_tests" expected_message = ( 'Language "es" is in required_languages on ' 'Model "A" but not in settings.MODELTRANS_AVAILABLE_LANGUAGES.') with self.assertRaisesMessage(ImproperlyConfigured, expected_message): translate_model(A)
def test_translate_model_with_existing_field(self): class TestModel2(models.Model): title = models.CharField(max_length=100) title_nl = models.CharField(max_length=100) i18n = TranslationField(fields=("title", )) class Meta: app_label = "django-modeltrans_tests" expected_message = ( 'Error adding translation field. Model "TestModel2" already ' 'contains a field named "title_nl".') with self.assertRaisesMessage(ImproperlyConfigured, expected_message): translate_model(TestModel2)
def test_non_id_pk(self): """This model doesn't have a id column""" class NonIdPrimaryKeyModel(models.Model): slug = models.SlugField(primary_key=True) title = models.CharField(max_length=100) i18n = TranslationField(fields=("title", )) class Meta: app_label = "tests" translate_model(NonIdPrimaryKeyModel) with CreateTestModel(NonIdPrimaryKeyModel): field, lookup_type = NonIdPrimaryKeyModel.objects.all()._get_field( "pk") self.assertEqual(field.name, "slug")
def test_order_by_fallback_chain(self): class TestObj(models.Model): title = models.CharField(max_length=100) i18n = TranslationField(fields=("title", )) class Meta: app_label = "tests" translate_model(TestObj) with CreateTestModel(TestObj): TestObj.objects.bulk_create([ TestObj(title="Falcon", title_nl="Valk"), TestObj(title="Frog", title_nl="Kikker", title_fr="Grenouilles", title_fy="Frosk"), TestObj(title="Fox", title_nl="Vos", title_fy="Foks"), TestObj(title="Gecko"), TestObj(title="Gerbil"), TestObj(title="Vulture", title_nl="Gier", title_fr="Vautour"), ]) # should use the 'default' fallback chain with override("nl"): qs = TestObj.objects.all().order_by("title_i18n") self.assertEqual(key(qs, "title_i18n"), "Gecko Gerbil Gier Kikker Valk Vos") # should use the 'fy' fallback chain with override("fy"): qs = TestObj.objects.all().order_by("title_i18n") self.assertEqual(key(qs, "title_i18n"), "Foks Frosk Gecko Gerbil Gier Valk") qs = TestObj.objects.all().order_by("-title_i18n") self.assertEqual(key(qs, "title_i18n"), "Valk Gier Gerbil Gecko Frosk Foks") # should use the 'default' fallback chain with override("fr"): qs = TestObj.objects.all().order_by("title_i18n") self.assertEqual( key(qs, "title_i18n"), "Falcon Fox Gecko Gerbil Grenouilles Vautour")
def test_model_meta_ordering_pk(self): """ When Model.Meta.ordering contains 'pk' """ class OrderByPkModel(models.Model): title = models.CharField(max_length=100) i18n = TranslationField(fields=("title", )) class Meta: app_label = "django-modeltrans_tests" ordering = ("-pk", ) translate_model(OrderByPkModel) sql = str(OrderByPkModel.objects.all().query) self.assertIn( 'ORDER BY "django-modeltrans_tests_orderbypkmodel"."id" DESC', sql)
def test_order_by_fallback_chain(self): class TestObj(models.Model): title = models.CharField(max_length=100) i18n = TranslationField(fields=('title', )) class Meta: app_label = 'django-modeltrans_tests' translate_model(TestObj) with CreateTestModel(TestObj): TestObj.objects.bulk_create([ TestObj(title='Falcon', title_nl='Valk'), TestObj(title='Frog', title_nl='Kikker', title_fr='Grenouilles', title_fy='Frosk'), TestObj(title='Fox', title_nl='Vos', title_fy='Foks'), TestObj(title='Gecko'), TestObj(title='Gerbil'), TestObj(title='Vulture', title_nl='Gier', title_fr='Vautour') ]) # should use the 'default' fallback chain with override('nl'): qs = TestObj.objects.all().order_by('title_i18n') self.assertEquals(key(qs, 'title_i18n'), ['Gecko', 'Gerbil', 'Gier', 'Kikker', 'Valk', 'Vos']) # should use the 'fy' fallback chain with override('fy'): expected = ['Foks', 'Frosk', 'Gecko', 'Gerbil', 'Gier', 'Valk'] qs = TestObj.objects.all().order_by('title_i18n') self.assertEquals(key(qs, 'title_i18n'), expected) expected.reverse() qs = TestObj.objects.all().order_by('-title_i18n') self.assertEquals(key(qs, 'title_i18n'), expected) # should use the 'default' fallback chain with override('fr'): qs = TestObj.objects.all().order_by('title_i18n') self.assertEquals(key(qs, 'title_i18n'), ['Falcon', 'Fox', 'Gecko', 'Gerbil', 'Grenouilles', 'Vautour'])
def __init__(self, *args, **kwargs): self.models = args if kwargs.get("translate", False): for Model in self.models: translate_model(Model)