Commit eb85e667 authored by Andriy Sokolovskiy's avatar Andriy Sokolovskiy Committed by Tim Graham
Browse files

[1.8.x] Fixed #24156 -- Fixed inherited related name of ManyToManyField.

Fixed situation when parent abstract model declares related_name='+'
and child models had an invalid queryset.

Backport of f7b29781 from master
parent 15359f1f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2540,7 +2540,7 @@ 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.rel.related_name = "_%s_+" % name
            self.rel.related_name = "_%s_%s_+" % (cls.__name__.lower(), name)

        super(ManyToManyField, self).contribute_to_class(cls, name, **kwargs)

+4 −0
Original line number Diff line number Diff line
@@ -17,3 +17,7 @@ Bugfixes

* Fixed system check crash on ``ForeignKey`` to abstract model
  (:ticket:`25503`).

* Fixed incorrect queries when you have multiple ``ManyToManyField``\s on
  different models that have the same field name, point to the same model, and
  have their reverse relations disabled (:ticket:`25545`).
+17 −0
Original line number Diff line number Diff line
@@ -35,3 +35,20 @@ class Article(models.Model):

    class Meta:
        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
+26 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ from django.db import transaction
from django.test import TestCase
from django.utils import six

from .models import Article, Publication
from .models import Article, InheritedArticleA, InheritedArticleB, Publication


class ManyToManyTests(TestCase):
@@ -415,3 +415,28 @@ class ManyToManyTests(TestCase):
        self.assertQuerysetEqual(self.a4.publications.all(), [])
        self.assertQuerysetEqual(self.p2.article_set.all(),
                                 ['<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>',
            ])
+10 −10
Original line number Diff line number Diff line
@@ -319,7 +319,7 @@ TEST_RESULTS = {
    'get_all_related_objects_with_model_hidden_local': {
        Person: (
            ('+', None),
            ('_people_hidden_+', None),
            ('_relating_people_hidden_+', None),
            ('Person_following_inherited+', None),
            ('Person_following_inherited+', None),
            ('Person_friends_inherited+', None),
@@ -334,7 +334,7 @@ TEST_RESULTS = {
        ),
        BasePerson: (
            ('+', None),
            ('_basepeople_hidden_+', None),
            ('_relating_basepeople_hidden_+', None),
            ('BasePerson_following_abstract+', None),
            ('BasePerson_following_abstract+', None),
            ('BasePerson_following_base+', None),
@@ -382,8 +382,8 @@ TEST_RESULTS = {
        Person: (
            ('+', BasePerson),
            ('+', None),
            ('_basepeople_hidden_+', BasePerson),
            ('_people_hidden_+', None),
            ('_relating_basepeople_hidden_+', BasePerson),
            ('_relating_people_hidden_+', None),
            ('BasePerson_following_abstract+', BasePerson),
            ('BasePerson_following_abstract+', BasePerson),
            ('BasePerson_following_base+', BasePerson),
@@ -416,7 +416,7 @@ TEST_RESULTS = {
        ),
        BasePerson: (
            ('+', None),
            ('_basepeople_hidden_+', None),
            ('_relating_basepeople_hidden_+', None),
            ('BasePerson_following_abstract+', None),
            ('BasePerson_following_abstract+', None),
            ('BasePerson_following_base+', None),
@@ -730,7 +730,7 @@ TEST_RESULTS = {
            ('friends_base_rel_+', None),
            ('followers_base', None),
            ('relating_basepeople', None),
            ('_basepeople_hidden_+', None),
            ('_relating_basepeople_hidden_+', None),
        ),
        Person: (
            ('friends_abstract_rel_+', BasePerson),
@@ -738,11 +738,11 @@ TEST_RESULTS = {
            ('friends_base_rel_+', BasePerson),
            ('followers_base', BasePerson),
            ('relating_basepeople', BasePerson),
            ('_basepeople_hidden_+', BasePerson),
            ('_relating_basepeople_hidden_+', BasePerson),
            ('friends_inherited_rel_+', None),
            ('followers_concrete', None),
            ('relating_people', None),
            ('_people_hidden_+', None),
            ('_relating_people_hidden_+', None),
        ),
        Relation: (
            ('m2m_abstract_rel', None),
@@ -757,13 +757,13 @@ TEST_RESULTS = {
            'friends_base_rel_+',
            'followers_base',
            'relating_basepeople',
            '_basepeople_hidden_+',
            '_relating_basepeople_hidden_+',
        ],
        Person: [
            'friends_inherited_rel_+',
            'followers_concrete',
            'relating_people',
            '_people_hidden_+',
            '_relating_people_hidden_+',
        ],
        Relation: [
            'm2m_abstract_rel',
Loading