Commit 353aecbf authored by Anssi Kääriäinen's avatar Anssi Kääriäinen Committed by Tim Graham
Browse files

Fixed #26153 -- Reallowed Q-objects in ForeignObject.get_extra_descriptor_filter().

parent 1d86d4c7
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ from django.apps import apps
from django.core import checks, exceptions
from django.db import connection, router
from django.db.backends import utils
from django.db.models import Q
from django.db.models.deletion import CASCADE, SET_DEFAULT, SET_NULL
from django.db.models.query_utils import PathInfo
from django.db.models.utils import make_model_tuple
@@ -337,8 +338,13 @@ class RelatedField(Field):
            rh_field.attname: getattr(obj, lh_field.attname)
            for lh_field, rh_field in self.related_fields
        }
        base_filter.update(self.get_extra_descriptor_filter(obj) or {})
        return base_filter
        descriptor_filter = self.get_extra_descriptor_filter(obj)
        base_q = Q(**base_filter)
        if isinstance(descriptor_filter, dict):
            return base_q & Q(**descriptor_filter)
        elif descriptor_filter:
            return base_q & descriptor_filter
        return base_q

    @property
    def swappable_setting(self):
+1 −1
Original line number Diff line number Diff line
@@ -166,7 +166,7 @@ class ForwardManyToOneDescriptor(object):
                rel_obj = None
            else:
                qs = self.get_queryset(instance=instance)
                qs = qs.filter(**self.field.get_reverse_related_filter(instance))
                qs = qs.filter(self.field.get_reverse_related_filter(instance))
                # Assuming the database enforces foreign keys, this won't fail.
                rel_obj = qs.get()
                # If this is a one-to-one relation, set the reverse accessor
+4 −0
Original line number Diff line number Diff line
@@ -17,3 +17,7 @@ Bugfixes

* Added system checks for query name clashes of hidden relationships
  (:ticket:`26162`).

* Fixed a regression for cases where
  ``ForeignObject.get_extra_descriptor_filter()`` returned a ``Q`` object
  (:ticket:`26153`).
+13 −0
Original line number Diff line number Diff line
@@ -44,6 +44,11 @@ class ActiveTranslationField(models.ForeignObject):
        setattr(cls, self.name, ArticleTranslationDescriptor(self))


class ActiveTranslationFieldWithQ(ActiveTranslationField):
    def get_extra_descriptor_filter(self, instance):
        return models.Q(lang=get_language())


@python_2_unicode_compatible
class Article(models.Model):
    active_translation = ActiveTranslationField(
@@ -54,6 +59,14 @@ class Article(models.Model):
        on_delete=models.CASCADE,
        null=True,
    )
    active_translation_q = ActiveTranslationFieldWithQ(
        'ArticleTranslation',
        from_fields=['id'],
        to_fields=['article'],
        related_name='+',
        on_delete=models.CASCADE,
        null=True,
    )
    pub_date = models.DateField()

    def __str__(self):
+13 −0
Original line number Diff line number Diff line
@@ -458,3 +458,16 @@ class TestModelCheckTests(SimpleTestCase):
            )

        self.assertEqual(Child._meta.get_field('parent').check(from_model=Child), [])


class TestExtraJoinFilterQ(TestCase):
    @translation.override('fi')
    def test_extra_join_filter_q(self):
        a = Article.objects.create(pub_date=datetime.datetime.today())
        ArticleTranslation.objects.create(article=a, lang='fi', title='title', body='body')
        qs = Article.objects.all()
        with self.assertNumQueries(2):
            self.assertEqual(qs[0].active_translation_q.title, 'title')
        qs = qs.select_related('active_translation_q')
        with self.assertNumQueries(1):
            self.assertEqual(qs[0].active_translation_q.title, 'title')