summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormanav014 <dpsman13016@gmail.com>2020-12-30 07:52:17 +0530
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-12-30 13:11:47 +0100
commita9a7421ab83361746549d574ca13438ba93c95fe (patch)
treeb37af83e6ffa3c9efba803d1bad5a717c32a310b
parent74fd233b1433da8c68de636172ee1c9c6d1c08c9 (diff)
Fixed #32294 -- Prevented ManyToManyField's hidden related name collisions between apps.
-rw-r--r--django/db/models/fields/related.py6
-rw-r--r--tests/invalid_models_tests/test_relative_fields.py28
-rw-r--r--tests/model_meta/results.py22
-rw-r--r--tests/model_meta/tests.py2
4 files changed, 44 insertions, 14 deletions
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 4c2247c08b..899ae8efe8 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -1614,7 +1614,11 @@ class ManyToManyField(RelatedField):
# related_name with one generated from the m2m field name. Django
# still uses backwards relations internally and we need to avoid
# clashes between multiple m2m fields with related_name == '+'.
- self.remote_field.related_name = "_%s_%s_+" % (cls.__name__.lower(), name)
+ self.remote_field.related_name = '_%s_%s_%s_+' % (
+ cls._meta.app_label,
+ cls.__name__.lower(),
+ name,
+ )
super().contribute_to_class(cls, name, **kwargs)
diff --git a/tests/invalid_models_tests/test_relative_fields.py b/tests/invalid_models_tests/test_relative_fields.py
index 82b1b426cf..8909b12214 100644
--- a/tests/invalid_models_tests/test_relative_fields.py
+++ b/tests/invalid_models_tests/test_relative_fields.py
@@ -3,7 +3,7 @@ from unittest import mock
from django.core.checks import Error, Warning as DjangoWarning
from django.db import connection, models
from django.test.testcases import SimpleTestCase
-from django.test.utils import isolate_apps, override_settings
+from django.test.utils import isolate_apps, modify_settings, override_settings
@isolate_apps('invalid_models_tests')
@@ -1025,6 +1025,32 @@ class ReverseQueryNameClashTests(SimpleTestCase):
),
])
+ @modify_settings(INSTALLED_APPS={'append': 'basic'})
+ @isolate_apps('basic', 'invalid_models_tests')
+ def test_no_clash_across_apps_without_accessor(self):
+ class Target(models.Model):
+ class Meta:
+ app_label = 'invalid_models_tests'
+
+ class Model(models.Model):
+ m2m = models.ManyToManyField(Target, related_name='+')
+
+ class Meta:
+ app_label = 'basic'
+
+ def _test():
+ # Define model with the same name.
+ class Model(models.Model):
+ m2m = models.ManyToManyField(Target, related_name='+')
+
+ class Meta:
+ app_label = 'invalid_models_tests'
+
+ self.assertEqual(Model.check(), [])
+
+ _test()
+ self.assertEqual(Model.check(), [])
+
@isolate_apps('invalid_models_tests')
class ExplicitRelatedNameClashTests(SimpleTestCase):
diff --git a/tests/model_meta/results.py b/tests/model_meta/results.py
index db8ccf650e..00aae72d60 100644
--- a/tests/model_meta/results.py
+++ b/tests/model_meta/results.py
@@ -321,7 +321,7 @@ TEST_RESULTS = {
'get_all_related_objects_with_model_hidden_local': {
Person: (
('+', None),
- ('_relating_people_hidden_+', None),
+ ('_model_meta_relating_people_hidden_+', None),
('Person_following_inherited+', None),
('Person_following_inherited+', None),
('Person_friends_inherited+', None),
@@ -339,7 +339,7 @@ TEST_RESULTS = {
),
ProxyPerson: (
('+', Person),
- ('_relating_people_hidden_+', Person),
+ ('_model_meta_relating_people_hidden_+', Person),
('Person_following_inherited+', Person),
('Person_following_inherited+', Person),
('Person_friends_inherited+', Person),
@@ -357,7 +357,7 @@ TEST_RESULTS = {
),
BasePerson: (
('+', None),
- ('_relating_basepeople_hidden_+', None),
+ ('_model_meta_relating_basepeople_hidden_+', None),
('BasePerson_following_abstract+', None),
('BasePerson_following_abstract+', None),
('BasePerson_following_base+', None),
@@ -408,8 +408,8 @@ TEST_RESULTS = {
Person: (
('+', BasePerson),
('+', None),
- ('_relating_basepeople_hidden_+', BasePerson),
- ('_relating_people_hidden_+', None),
+ ('_model_meta_relating_basepeople_hidden_+', BasePerson),
+ ('_model_meta_relating_people_hidden_+', None),
('BasePerson_following_abstract+', BasePerson),
('BasePerson_following_abstract+', BasePerson),
('BasePerson_following_base+', BasePerson),
@@ -446,8 +446,8 @@ TEST_RESULTS = {
ProxyPerson: (
('+', BasePerson),
('+', Person),
- ('_relating_basepeople_hidden_+', BasePerson),
- ('_relating_people_hidden_+', Person),
+ ('_model_meta_relating_basepeople_hidden_+', BasePerson),
+ ('_model_meta_relating_people_hidden_+', Person),
('BasePerson_following_abstract+', BasePerson),
('BasePerson_following_abstract+', BasePerson),
('BasePerson_following_base+', BasePerson),
@@ -483,7 +483,7 @@ TEST_RESULTS = {
),
BasePerson: (
('+', None),
- ('_relating_basepeople_hidden_+', None),
+ ('_model_meta_relating_basepeople_hidden_+', None),
('BasePerson_following_abstract+', None),
('BasePerson_following_abstract+', None),
('BasePerson_following_base+', None),
@@ -822,7 +822,7 @@ TEST_RESULTS = {
('friends_base_rel_+', None),
('followers_base', None),
('relating_basepeople', None),
- ('_relating_basepeople_hidden_+', None),
+ ('_model_meta_relating_basepeople_hidden_+', None),
),
Person: (
('friends_abstract_rel_+', BasePerson),
@@ -830,7 +830,7 @@ TEST_RESULTS = {
('friends_base_rel_+', BasePerson),
('followers_base', BasePerson),
('relating_basepeople', BasePerson),
- ('_relating_basepeople_hidden_+', BasePerson),
+ ('_model_meta_relating_basepeople_hidden_+', BasePerson),
('friends_inherited_rel_+', None),
('followers_concrete', None),
('relating_people', None),
@@ -849,7 +849,7 @@ TEST_RESULTS = {
'friends_base_rel_+',
'followers_base',
'relating_basepeople',
- '_relating_basepeople_hidden_+',
+ '_model_meta_relating_basepeople_hidden_+',
],
Person: [
'friends_inherited_rel_+',
diff --git a/tests/model_meta/tests.py b/tests/model_meta/tests.py
index 32bcfbc9e6..b3d469a903 100644
--- a/tests/model_meta/tests.py
+++ b/tests/model_meta/tests.py
@@ -257,7 +257,7 @@ class RelationTreeTests(SimpleTestCase):
self.assertEqual(
sorted(field.related_query_name() for field in BasePerson._meta._relation_tree),
sorted([
- '+', '_relating_basepeople_hidden_+', 'BasePerson_following_abstract+',
+ '+', '_model_meta_relating_basepeople_hidden_+', 'BasePerson_following_abstract+',
'BasePerson_following_abstract+', 'BasePerson_following_base+', 'BasePerson_following_base+',
'BasePerson_friends_abstract+', 'BasePerson_friends_abstract+', 'BasePerson_friends_base+',
'BasePerson_friends_base+', 'BasePerson_m2m_abstract+', 'BasePerson_m2m_base+', 'Relating_basepeople+',