diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 0788db48f8..b038fdf116 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -119,10 +119,18 @@ class RelatedField(Field): import re import keyword related_name = self.remote_field.related_name - - is_valid_id = (related_name and re.match('^[a-zA-Z_][a-zA-Z0-9_]*$', related_name) - and not keyword.iskeyword(related_name)) - if related_name and not (is_valid_id or related_name.endswith('+')): + if not related_name: + return [] + is_valid_id = True + if keyword.iskeyword(related_name): + is_valid_id = False + if six.PY3: + if not related_name.isidentifier(): + is_valid_id = False + else: + if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*\Z', related_name): + is_valid_id = False + if not (is_valid_id or related_name.endswith('+')): return [ checks.Error( "The name '%s' is invalid related_name for field %s.%s" % diff --git a/docs/releases/1.8.3.txt b/docs/releases/1.8.3.txt index 38bcaf5374..512d6ff7c7 100644 --- a/docs/releases/1.8.3.txt +++ b/docs/releases/1.8.3.txt @@ -82,3 +82,6 @@ Bugfixes * Fixed a regression when deleting a model through the admin that has a ``GenericRelation`` with a ``related_query_name`` (:ticket:`24940`). + +* Reallowed non-ASCII values for ``ForeignKey.related_name`` on Python 3 by + fixing the false positive system check (:ticket:`25016`). diff --git a/docs/spelling_wordlist b/docs/spelling_wordlist index 293aa6f816..ff37b3159e 100644 --- a/docs/spelling_wordlist +++ b/docs/spelling_wordlist @@ -625,6 +625,7 @@ quo quoteless Radziej rc +reallowed rebase rebased rebasing diff --git a/tests/invalid_models_tests/test_relative_fields.py b/tests/invalid_models_tests/test_relative_fields.py index b6ac3de722..5d174d0c9b 100644 --- a/tests/invalid_models_tests/test_relative_fields.py +++ b/tests/invalid_models_tests/test_relative_fields.py @@ -5,6 +5,7 @@ from django.core.checks import Error, Warning as DjangoWarning from django.db import models from django.test.testcases import skipIfDBFeature from django.test.utils import override_settings +from django.utils import six from .base import IsolatedModelsTestCase @@ -559,9 +560,12 @@ class RelativeFieldTests(IsolatedModelsTestCase): 'contains_%s_whitespace' % whitespace, 'ends_with_with_illegal_non_alphanumeric_%s' % illegal_non_alphanumeric, 'ends_with_whitespace_%s' % whitespace, - # Python's keyword - 'with', + 'with', # a Python keyword + 'related_name\n', ] + # Python 2 crashes on non-ASCII strings. + if six.PY3: + invalid_related_names.append(',') class Parent(models.Model): pass @@ -600,6 +604,9 @@ class RelativeFieldTests(IsolatedModelsTestCase): '_+', '+', ] + # Python 2 crashes on non-ASCII strings. + if six.PY3: + related_names.extend(['試', '試驗+']) class Parent(models.Model): pass