diff options
| author | Akis Kesoglou <akiskesoglou@gmail.com> | 2014-02-19 20:01:55 +0200 |
|---|---|---|
| committer | Anssi Kääriäinen <akaariai@gmail.com> | 2014-03-05 22:33:58 +0200 |
| commit | c627da0ccc12861163f28177aa7538b420a9d310 (patch) | |
| tree | d2c3d58f3083bb502f541a9201811e2cdaefd65b /tests/invalid_models_tests/test_relative_fields.py | |
| parent | 95c74b9d699c29fe808684774548e2864d64665a (diff) | |
Fixed #14549 - Removed restriction of single FKs on intermediary tables
Thanks to Loic Bistuer for review. Minor changes to error messages
done by committer.
Diffstat (limited to 'tests/invalid_models_tests/test_relative_fields.py')
| -rw-r--r-- | tests/invalid_models_tests/test_relative_fields.py | 92 |
1 files changed, 89 insertions, 3 deletions
diff --git a/tests/invalid_models_tests/test_relative_fields.py b/tests/invalid_models_tests/test_relative_fields.py index 2d54650414..b04f2d4f17 100644 --- a/tests/invalid_models_tests/test_relative_fields.py +++ b/tests/invalid_models_tests/test_relative_fields.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from django.core.checks import Error from django.db import models +from django.db.models.fields import FieldDoesNotExist from django.test.utils import override_settings from django.test.testcases import skipIfDBFeature @@ -81,7 +82,9 @@ class RelativeFieldTests(IsolatedModelsTestCase): Error( ("The model is used as an intermediate model by " "'invalid_models_tests.Group.field', but it has more than one " - "foreign key to 'Person', which is ambiguous."), + "foreign key to 'Person', which is ambiguous. You must specify " + "which foreign key Django should use via the through_fields " + "keyword argument."), hint=('If you want to create a recursive relationship, use ' 'ForeignKey("self", symmetrical=False, ' 'through="AmbiguousRelationship").'), @@ -205,8 +208,10 @@ class RelativeFieldTests(IsolatedModelsTestCase): Error( ("The model is used as an intermediate model by " "'invalid_models_tests.Person.friends', but it has more than two " - "foreign keys to 'Person', which is ambiguous."), - hint=None, + "foreign keys to 'Person', which is ambiguous. You must specify " + "which two foreign keys Django should use via the through_fields " + "keyword argument."), + hint='Use through_fields to specify which two foreign keys Django should use.', obj=InvalidRelationship, id='fields.E333', ), @@ -1051,3 +1056,84 @@ class ComplexClashTests(IsolatedModelsTestCase): ), ] self.assertEqual(errors, expected) + + +class M2mThroughFieldsTests(IsolatedModelsTestCase): + def test_m2m_field_argument_validation(self): + """ + Tests that ManyToManyField accepts the ``through_fields`` kwarg + only if an intermediary table is specified. + """ + class Fan(models.Model): + pass + + self.assertRaisesMessage( + ValueError, 'Cannot specify through_fields without a through model', + models.ManyToManyField, Fan, through_fields=('f1', 'f2')) + + def test_invalid_m2m_field(self): + """ + Tests that providing invalid source field name to ManyToManyField.through_fields + raises FieldDoesNotExist. + """ + class Fan(models.Model): + pass + + class Event(models.Model): + invitees = models.ManyToManyField(Fan, through='Invitation', through_fields=('invalid_field', 'invitee')) + + 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() + + def test_invalid_m2m_reverse_field(self): + """ + Tests that providing invalid reverse field name to ManyToManyField.through_fields + raises FieldDoesNotExist. + """ + class Fan(models.Model): + pass + + class Event(models.Model): + invitees = models.ManyToManyField(Fan, through='Invitation', through_fields=('event', 'invalid_field')) + + 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() + + def test_explicit_field_names(self): + """ + Tests that if ``through_fields`` kwarg is given, it must specify both + link fields of the intermediary table. + """ + class Fan(models.Model): + pass + + class Event(models.Model): + invitees = models.ManyToManyField(Fan, through='Invitation', through_fields=(None, 'invitee')) + + class Invitation(models.Model): + event = models.ForeignKey(Event) + invitee = models.ForeignKey(Fan) + inviter = models.ForeignKey(Fan, related_name='+') + + field = Event._meta.get_field('invitees') + 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, + obj=field, + id='fields.E337')] + self.assertEqual(expected, errors) |
