diff options
Diffstat (limited to 'tests/invalid_models_tests/test_relative_fields.py')
| -rw-r--r-- | tests/invalid_models_tests/test_relative_fields.py | 86 |
1 files changed, 69 insertions, 17 deletions
diff --git a/tests/invalid_models_tests/test_relative_fields.py b/tests/invalid_models_tests/test_relative_fields.py index b04f2d4f17..dabbe61723 100644 --- a/tests/invalid_models_tests/test_relative_fields.py +++ b/tests/invalid_models_tests/test_relative_fields.py @@ -240,6 +240,32 @@ class RelativeFieldTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) + def test_symmetric_self_reference_with_intermediate_table_and_through_fields(self): + """Using through_fields in a m2m with an intermediate model shouldn't mask its incompatibility with symmetry.""" + class Person(models.Model): + # Explicit symmetrical=True. + friends = models.ManyToManyField('self', + symmetrical=True, + through="Relationship", + through_fields=('first', 'second')) + + class Relationship(models.Model): + first = models.ForeignKey(Person, related_name="rel_from_set") + second = models.ForeignKey(Person, related_name="rel_to_set") + referee = models.ForeignKey(Person, related_name="referred") + + field = Person._meta.get_field('friends') + errors = field.check(from_model=Person) + expected = [ + Error( + 'Many-to-many fields with intermediate tables must not be symmetrical.', + hint=None, + obj=field, + id='fields.E332', + ), + ] + self.assertEqual(errors, expected) + def test_foreign_key_to_abstract_model(self): class Model(models.Model): foreign_key = models.ForeignKey('AbstractModel') @@ -1071,43 +1097,69 @@ class M2mThroughFieldsTests(IsolatedModelsTestCase): ValueError, 'Cannot specify through_fields without a through model', models.ManyToManyField, Fan, through_fields=('f1', 'f2')) - def test_invalid_m2m_field(self): + def test_invalid_order(self): """ - Tests that providing invalid source field name to ManyToManyField.through_fields - raises FieldDoesNotExist. + Tests that mixing up the order of link fields to ManyToManyField.through_fields + triggers validation errors. """ class Fan(models.Model): pass class Event(models.Model): - invitees = models.ManyToManyField(Fan, through='Invitation', through_fields=('invalid_field', 'invitee')) + invitees = models.ManyToManyField(Fan, through='Invitation', through_fields=('invitee', 'event')) class Invitation(models.Model): event = models.ForeignKey(Event) invitee = models.ForeignKey(Fan) inviter = models.ForeignKey(Fan, related_name='+') - with self.assertRaisesMessage(FieldDoesNotExist, 'invalid_field'): - Event().invitees.all() + field = Event._meta.get_field('invitees') + errors = field.check(from_model=Event) + expected = [ + Error( + ("'Invitation.invitee' is not a foreign key to 'Event'."), + hint="Did you mean one of the following foreign keys to 'Event': event?", + obj=field, + id='fields.E339'), + Error( + ("'Invitation.event' is not a foreign key to 'Fan'."), + hint="Did you mean one of the following foreign keys to 'Fan': invitee, inviter?", + obj=field, + id='fields.E339'), + ] + self.assertEqual(expected, errors) - def test_invalid_m2m_reverse_field(self): + def test_invalid_field(self): """ - Tests that providing invalid reverse field name to ManyToManyField.through_fields - raises FieldDoesNotExist. + Tests that providing invalid field names to ManyToManyField.through_fields + triggers validation errors. """ class Fan(models.Model): pass class Event(models.Model): - invitees = models.ManyToManyField(Fan, through='Invitation', through_fields=('event', 'invalid_field')) + invitees = models.ManyToManyField(Fan, through='Invitation', through_fields=('invalid_field_1', 'invalid_field_2')) class Invitation(models.Model): event = models.ForeignKey(Event) invitee = models.ForeignKey(Fan) inviter = models.ForeignKey(Fan, related_name='+') - with self.assertRaisesMessage(FieldDoesNotExist, 'invalid_field'): - Event().invitees.all() + field = Event._meta.get_field('invitees') + errors = field.check(from_model=Event) + expected = [ + Error( + ("The intermediary model 'invalid_models_tests.Invitation' has no field 'invalid_field_1'."), + hint="Did you mean one of the following foreign keys to 'Event': event?", + obj=field, + id='fields.E338'), + Error( + ("The intermediary model 'invalid_models_tests.Invitation' has no field 'invalid_field_2'."), + hint="Did you mean one of the following foreign keys to 'Fan': invitee, inviter?", + obj=field, + id='fields.E338'), + ] + self.assertEqual(expected, errors) def test_explicit_field_names(self): """ @@ -1129,11 +1181,11 @@ class M2mThroughFieldsTests(IsolatedModelsTestCase): errors = field.check(from_model=Event) expected = [ Error( - ("The field is given an iterable for through_fields, " - "which does not provide the names for both link fields " - "that Django should use for the relation through model " - "'invalid_models_tests.Invitation'."), - hint=None, + ("Field specifies 'through_fields' but does not provide the names " + "of the two link fields that should be used for the relation " + "through model 'invalid_models_tests.Invitation'."), + hint=("Make sure you specify 'through_fields' as " + "through_fields=('field1', 'field2')"), obj=field, id='fields.E337')] self.assertEqual(expected, errors) |
