From 43a61a0bcca33a842dab2ee153ec2d658514afdd Mon Sep 17 00:00:00 2001 From: Braden MacDonald Date: Sun, 10 Mar 2013 16:39:14 -0700 Subject: [PATCH] Add tests for foreign key reverse relations, and fix some issues. Still incomplete. ref deschler/django-modeltranslation#161 --- modeltranslation/fields.py | 4 ++ modeltranslation/tests/__init__.py | 70 ++++++++++++++++++++++++++++++ modeltranslation/tests/models.py | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/modeltranslation/fields.py b/modeltranslation/fields.py index 6de22b6..e7df127 100644 --- a/modeltranslation/fields.py +++ b/modeltranslation/fields.py @@ -114,7 +114,11 @@ class TranslationField(object): import copy current = self.related.get_accessor_name() self.rel = copy.copy(self.rel) # Since fields cannot share the same rel object. + self.related = copy.copy(self.related) + self.related.field = self # We need self.related.field to point to this instance self.rel.related_name = build_localized_fieldname(current, self.language) + if hasattr(self.rel.to._meta, '_related_objects_cache'): + del self.rel.to._meta._related_objects_cache # Django 1.5 changed definition of __hash__ for fields to be fine with hash requirements. # It spoiled our machinery, since TranslationField has the same creation_counter as its diff --git a/modeltranslation/tests/__init__.py b/modeltranslation/tests/__init__.py index aea5d60..455d42e 100644 --- a/modeltranslation/tests/__init__.py +++ b/modeltranslation/tests/__init__.py @@ -680,6 +680,76 @@ class ForeignKeyFieldsTest(ModeltranslationTestBase): self.failUnlessEqual(inst.optional_en_id, test_inst2.pk) self.failUnlessEqual(inst.optional_en.title, 'title2_en') + def test_reverse_relations(self): + test_inst = models.TestModel(title_en='title_en', title_de='title_de') + test_inst.save() + + # Instantiate many 'ForeignKeyModel' instances: + fk_inst_both = models.ForeignKeyModel(test_de=test_inst, test_en=test_inst) + fk_inst_both.save() + fk_inst_de = models.ForeignKeyModel(test_de_id=test_inst.pk) + fk_inst_de.save() + fk_inst_en = models.ForeignKeyModel(test_en=test_inst) + fk_inst_en.save() + + # Check that the reverse accessors are created on the model: + testmodel_fields = models.TestModel._meta.get_all_field_names() + self.assertIn('test_fks', testmodel_fields) + self.assertIn('test_fks_de', testmodel_fields) + self.assertIn('test_fks_en', testmodel_fields) + self.assertIn('foreignkeymodel_set', testmodel_fields) # FIXME + self.assertIn('foreignkeymodel_set_de', testmodel_fields) + self.assertIn('foreignkeymodel_set_en', testmodel_fields) + + # Check the german reverse accessor: + self.assertIn(fk_inst_both, test_inst.test_fks_de.all()) + self.assertIn(fk_inst_de, test_inst.test_fks_de.all()) + self.assertNotIn(fk_inst_en, test_inst.test_fks_de.all()) + + # Check the English reverse accessor: + self.assertIn(fk_inst_both, test_inst.test_fks_en.all()) + self.assertIn(fk_inst_en, test_inst.test_fks_en.all()) + self.assertNotIn(fk_inst_de, test_inst.test_fks_en.all()) + + # Check the default reverse accessor: + trans_real.activate("de") + self.assertIn(fk_inst_de, test_inst.test_fks.all()) + self.assertNotIn(fk_inst_en, test_inst.test_fks.all()) + trans_real.activate("en") + self.assertIn(fk_inst_en, test_inst.test_fks.all()) + self.assertNotIn(fk_inst_de, test_inst.test_fks.all()) + + # Check filtering: + self.failUnlessEqual(models.TestModel.objects.filter(test_fks=fk_inst_de).count(), 1) + self.failUnlessEqual(models.TestModel.objects.filter(test_fks__id=fk_inst_de.pk).count(), 1) + self.failUnlessEqual(models.TestModel.objects.filter(test_fks=fk_inst_en).count(), 0) + self.failUnlessEqual(models.TestModel.objects.filter(test_fks_en=fk_inst_en).count(), 1) + trans_real.activate("en") + self.failUnlessEqual(models.TestModel.objects.filter(test_fks=fk_inst_en).count(), 1) # FIXME + self.failUnlessEqual(models.TestModel.objects.filter(test_fks__id=fk_inst_en.pk).count(), 1) # FIXME + self.failUnlessEqual(models.TestModel.objects.filter(test_fks=fk_inst_de).count(), 0) # FIXME + # TODO: test filter() on a relation to a non-translated model - FIXME + + # Check assignment + trans_real.activate("de") + test_inst2 = models.TestModel(title_en='title_en', title_de='title_de') + test_inst2.save() + test_inst2.test_fks = [fk_inst_de, fk_inst_both] + test_inst2.test_fks_en = (fk_inst_en, fk_inst_both) + + self.assertEqual(fk_inst_both.test.pk, test_inst2.pk) + self.assertEqual(fk_inst_both.test_id, test_inst2.pk) + self.assertEqual(fk_inst_both.test_de, test_inst2) + self.assertIn(fk_inst_both, test_inst2.test_fks_de.all()) + self.assertIn(fk_inst_de, test_inst2.test_fks_de.all()) + self.assertIn(fk_inst_de, test_inst2.test_fks.all()) + self.assertNotIn(fk_inst_en, test_inst2.test_fks_de.all()) + trans_real.activate("en") + self.assertIn(fk_inst_both, test_inst2.test_fks.all()) + self.assertIn(fk_inst_en, test_inst2.test_fks.all()) + self.assertNotIn(fk_inst_de, test_inst2.test_fks.all()) + self.assertNotIn(fk_inst_de, test_inst2.test_fks_en.all()) + class OtherFieldsTest(ModeltranslationTestBase): def test_translated_models(self): diff --git a/modeltranslation/tests/models.py b/modeltranslation/tests/models.py index 3c318cd..675a124 100644 --- a/modeltranslation/tests/models.py +++ b/modeltranslation/tests/models.py @@ -38,7 +38,7 @@ class FileFieldsModel(models.Model): ########## Foreign Key fields testing class ForeignKeyModel(models.Model): - test = models.ForeignKey(TestModel, null=True, related_name="test_fk") + test = models.ForeignKey(TestModel, null=True, related_name="test_fks") optional = models.ForeignKey(TestModel, blank=True, null=True)