Kaydet (Commit) f7b29781 authored tarafından Andriy Sokolovskiy's avatar Andriy Sokolovskiy Kaydeden (comit) Tim Graham

Fixed #24156 -- Fixed inherited related name of ManyToManyField.

Fixed situation when parent abstract model declares related_name='+',
and child models had an invalid queryset.
üst ec74dba2
...@@ -2626,7 +2626,7 @@ class ManyToManyField(RelatedField): ...@@ -2626,7 +2626,7 @@ class ManyToManyField(RelatedField):
# related_name with one generated from the m2m field name. Django # related_name with one generated from the m2m field name. Django
# still uses backwards relations internally and we need to avoid # still uses backwards relations internally and we need to avoid
# clashes between multiple m2m fields with related_name == '+'. # clashes between multiple m2m fields with related_name == '+'.
self.remote_field.related_name = "_%s_+" % name self.remote_field.related_name = "_%s_%s_+" % (cls.__name__.lower(), name)
super(ManyToManyField, self).contribute_to_class(cls, name, **kwargs) super(ManyToManyField, self).contribute_to_class(cls, name, **kwargs)
......
...@@ -35,3 +35,20 @@ class Article(models.Model): ...@@ -35,3 +35,20 @@ class Article(models.Model):
class Meta: class Meta:
ordering = ('headline',) ordering = ('headline',)
# Models to test correct related_name inheritance
class AbstractArticle(models.Model):
class Meta:
abstract = True
ordering = ('title',)
publications = models.ManyToManyField(Publication, name='publications', related_name='+')
class InheritedArticleA(AbstractArticle):
pass
class InheritedArticleB(AbstractArticle):
pass
...@@ -4,7 +4,7 @@ from django.db import transaction ...@@ -4,7 +4,7 @@ from django.db import transaction
from django.test import TestCase from django.test import TestCase
from django.utils import six from django.utils import six
from .models import Article, Publication from .models import Article, InheritedArticleA, InheritedArticleB, Publication
class ManyToManyTests(TestCase): class ManyToManyTests(TestCase):
...@@ -454,3 +454,28 @@ class ManyToManyTests(TestCase): ...@@ -454,3 +454,28 @@ class ManyToManyTests(TestCase):
self.assertQuerysetEqual(self.a4.publications.all(), []) self.assertQuerysetEqual(self.a4.publications.all(), [])
self.assertQuerysetEqual(self.p2.article_set.all(), self.assertQuerysetEqual(self.p2.article_set.all(),
['<Article: NASA finds intelligent life on Earth>']) ['<Article: NASA finds intelligent life on Earth>'])
def test_inherited_models_selects(self):
"""
#24156 - Objects from child models where the parent's m2m field uses
related_name='+' should be retrieved correctly.
"""
a = InheritedArticleA.objects.create()
b = InheritedArticleB.objects.create()
a.publications.add(self.p1, self.p2)
self.assertQuerysetEqual(a.publications.all(),
[
'<Publication: Science News>',
'<Publication: The Python Journal>',
])
self.assertQuerysetEqual(b.publications.all(), [])
b.publications.add(self.p3)
self.assertQuerysetEqual(a.publications.all(),
[
'<Publication: Science News>',
'<Publication: The Python Journal>',
])
self.assertQuerysetEqual(b.publications.all(),
[
'<Publication: Science Weekly>',
])
...@@ -319,7 +319,7 @@ TEST_RESULTS = { ...@@ -319,7 +319,7 @@ TEST_RESULTS = {
'get_all_related_objects_with_model_hidden_local': { 'get_all_related_objects_with_model_hidden_local': {
Person: ( Person: (
('+', None), ('+', None),
('_people_hidden_+', None), ('_relating_people_hidden_+', None),
('Person_following_inherited+', None), ('Person_following_inherited+', None),
('Person_following_inherited+', None), ('Person_following_inherited+', None),
('Person_friends_inherited+', None), ('Person_friends_inherited+', None),
...@@ -334,7 +334,7 @@ TEST_RESULTS = { ...@@ -334,7 +334,7 @@ TEST_RESULTS = {
), ),
BasePerson: ( BasePerson: (
('+', None), ('+', None),
('_basepeople_hidden_+', None), ('_relating_basepeople_hidden_+', None),
('BasePerson_following_abstract+', None), ('BasePerson_following_abstract+', None),
('BasePerson_following_abstract+', None), ('BasePerson_following_abstract+', None),
('BasePerson_following_base+', None), ('BasePerson_following_base+', None),
...@@ -382,8 +382,8 @@ TEST_RESULTS = { ...@@ -382,8 +382,8 @@ TEST_RESULTS = {
Person: ( Person: (
('+', BasePerson), ('+', BasePerson),
('+', None), ('+', None),
('_basepeople_hidden_+', BasePerson), ('_relating_basepeople_hidden_+', BasePerson),
('_people_hidden_+', None), ('_relating_people_hidden_+', None),
('BasePerson_following_abstract+', BasePerson), ('BasePerson_following_abstract+', BasePerson),
('BasePerson_following_abstract+', BasePerson), ('BasePerson_following_abstract+', BasePerson),
('BasePerson_following_base+', BasePerson), ('BasePerson_following_base+', BasePerson),
...@@ -416,7 +416,7 @@ TEST_RESULTS = { ...@@ -416,7 +416,7 @@ TEST_RESULTS = {
), ),
BasePerson: ( BasePerson: (
('+', None), ('+', None),
('_basepeople_hidden_+', None), ('_relating_basepeople_hidden_+', None),
('BasePerson_following_abstract+', None), ('BasePerson_following_abstract+', None),
('BasePerson_following_abstract+', None), ('BasePerson_following_abstract+', None),
('BasePerson_following_base+', None), ('BasePerson_following_base+', None),
...@@ -730,7 +730,7 @@ TEST_RESULTS = { ...@@ -730,7 +730,7 @@ TEST_RESULTS = {
('friends_base_rel_+', None), ('friends_base_rel_+', None),
('followers_base', None), ('followers_base', None),
('relating_basepeople', None), ('relating_basepeople', None),
('_basepeople_hidden_+', None), ('_relating_basepeople_hidden_+', None),
), ),
Person: ( Person: (
('friends_abstract_rel_+', BasePerson), ('friends_abstract_rel_+', BasePerson),
...@@ -738,11 +738,11 @@ TEST_RESULTS = { ...@@ -738,11 +738,11 @@ TEST_RESULTS = {
('friends_base_rel_+', BasePerson), ('friends_base_rel_+', BasePerson),
('followers_base', BasePerson), ('followers_base', BasePerson),
('relating_basepeople', BasePerson), ('relating_basepeople', BasePerson),
('_basepeople_hidden_+', BasePerson), ('_relating_basepeople_hidden_+', BasePerson),
('friends_inherited_rel_+', None), ('friends_inherited_rel_+', None),
('followers_concrete', None), ('followers_concrete', None),
('relating_people', None), ('relating_people', None),
('_people_hidden_+', None), ('_relating_people_hidden_+', None),
), ),
Relation: ( Relation: (
('m2m_abstract_rel', None), ('m2m_abstract_rel', None),
...@@ -757,13 +757,13 @@ TEST_RESULTS = { ...@@ -757,13 +757,13 @@ TEST_RESULTS = {
'friends_base_rel_+', 'friends_base_rel_+',
'followers_base', 'followers_base',
'relating_basepeople', 'relating_basepeople',
'_basepeople_hidden_+', '_relating_basepeople_hidden_+',
], ],
Person: [ Person: [
'friends_inherited_rel_+', 'friends_inherited_rel_+',
'followers_concrete', 'followers_concrete',
'relating_people', 'relating_people',
'_people_hidden_+', '_relating_people_hidden_+',
], ],
Relation: [ Relation: [
'm2m_abstract_rel', 'm2m_abstract_rel',
......
...@@ -248,7 +248,7 @@ class RelationTreeTests(TestCase): ...@@ -248,7 +248,7 @@ class RelationTreeTests(TestCase):
self.assertEqual( self.assertEqual(
sorted([field.related_query_name() for field in BasePerson._meta._relation_tree]), sorted([field.related_query_name() for field in BasePerson._meta._relation_tree]),
sorted([ sorted([
'+', '_basepeople_hidden_+', 'BasePerson_following_abstract+', 'BasePerson_following_abstract+', '+', '_relating_basepeople_hidden_+', 'BasePerson_following_abstract+', 'BasePerson_following_abstract+',
'BasePerson_following_base+', 'BasePerson_following_base+', 'BasePerson_friends_abstract+', 'BasePerson_following_base+', 'BasePerson_following_base+', 'BasePerson_friends_abstract+',
'BasePerson_friends_abstract+', 'BasePerson_friends_base+', 'BasePerson_friends_base+', 'BasePerson_friends_abstract+', 'BasePerson_friends_base+', 'BasePerson_friends_base+',
'BasePerson_m2m_abstract+', 'BasePerson_m2m_base+', 'Relating_basepeople+', 'BasePerson_m2m_abstract+', 'BasePerson_m2m_base+', 'Relating_basepeople+',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment