summaryrefslogtreecommitdiff
path: root/tests/invalid_models_tests/test_relative_fields.py
diff options
context:
space:
mode:
authorAndré Ericson <de.ericson@gmail.com>2014-10-04 20:47:26 -0300
committerAndré Ericson <de.ericson@gmail.com>2014-10-04 20:47:26 -0300
commit1e5e2a470768549117ac4696ce3e8b4e51d65664 (patch)
tree3ef4e3b818974378d435939771bb2d5495ae36aa /tests/invalid_models_tests/test_relative_fields.py
parent8c581ff39475c1b3b25d60945cc1c73a7f8eb1be (diff)
Fixed #22064 -- Add check for related_name
Validates that related_name is a valid Python id or ends with a '+' and it's not a keyword. Without a check it passed silently leading to unpredictable problems. Thanks Konrad Świat for the initial work.
Diffstat (limited to 'tests/invalid_models_tests/test_relative_fields.py')
-rw-r--r--tests/invalid_models_tests/test_relative_fields.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/tests/invalid_models_tests/test_relative_fields.py b/tests/invalid_models_tests/test_relative_fields.py
index 4b4c5947f3..9781ecc2ba 100644
--- a/tests/invalid_models_tests/test_relative_fields.py
+++ b/tests/invalid_models_tests/test_relative_fields.py
@@ -546,6 +546,73 @@ class RelativeFieldTests(IsolatedModelsTestCase):
errors = field.check(from_model=Model)
self.assertEqual(errors, [expected_error])
+ def test_related_field_has_invalid_related_name(self):
+ digit = 0
+ illegal_non_alphanumeric = '!'
+ whitespace = '\t'
+
+ invalid_related_names = [
+ '%s_begins_with_digit' % digit,
+ '%s_begins_with_illegal_non_alphanumeric' % illegal_non_alphanumeric,
+ '%s_begins_with_whitespace' % whitespace,
+ 'contains_%s_illegal_non_alphanumeric' % illegal_non_alphanumeric,
+ 'contains_%s_whitespace' % whitespace,
+ 'ends_with_with_illegal_non_alphanumeric_%s' % illegal_non_alphanumeric,
+ 'ends_with_whitespace_%s' % whitespace,
+ # Python's keyword
+ 'with',
+ ]
+
+ class Parent(models.Model):
+ pass
+
+ for invalid_related_name in invalid_related_names:
+ Child = type(str('Child_%s') % str(invalid_related_name), (models.Model,), {
+ 'parent': models.ForeignKey('Parent', related_name=invalid_related_name),
+ '__module__': Parent.__module__,
+ })
+
+ field = Child._meta.get_field('parent')
+ errors = Child.check()
+ expected = [
+ Error(
+ "The name '%s' is invalid related_name for field Child_%s.parent"
+ % (invalid_related_name, invalid_related_name),
+ hint="Related name must be a valid Python identifier or end with a '+'",
+ obj=field,
+ id='fields.E306',
+ ),
+ ]
+ self.assertEqual(errors, expected)
+
+ def test_related_field_has_valid_related_name(self):
+ lowercase = 'a'
+ uppercase = 'A'
+ digit = 0
+
+ related_names = [
+ '%s_starts_with_lowercase' % lowercase,
+ '%s_tarts_with_uppercase' % uppercase,
+ '_starts_with_underscore',
+ 'contains_%s_digit' % digit,
+ 'ends_with_plus+',
+ '_',
+ '_+',
+ '+',
+ ]
+
+ class Parent(models.Model):
+ pass
+
+ for related_name in related_names:
+ Child = type(str('Child_%s') % str(related_name), (models.Model,), {
+ 'parent': models.ForeignKey('Parent', related_name=related_name),
+ '__module__': Parent.__module__,
+ })
+
+ errors = Child.check()
+ self.assertFalse(errors)
+
class AccessorClashTests(IsolatedModelsTestCase):