mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #32294 -- Prevented ManyToManyField's hidden related name collisions between apps.
This commit is contained in:
parent
74fd233b14
commit
a9a7421ab8
@ -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)
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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_+',
|
||||
|
@ -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+',
|
||||
|
Loading…
Reference in New Issue
Block a user