Kaydet (Commit) 353aecbf authored tarafından Anssi Kääriäinen's avatar Anssi Kääriäinen Kaydeden (comit) Tim Graham

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

üst 1d86d4c7
...@@ -8,6 +8,7 @@ from django.apps import apps ...@@ -8,6 +8,7 @@ from django.apps import apps
from django.core import checks, exceptions from django.core import checks, exceptions
from django.db import connection, router from django.db import connection, router
from django.db.backends import utils 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.deletion import CASCADE, SET_DEFAULT, SET_NULL
from django.db.models.query_utils import PathInfo from django.db.models.query_utils import PathInfo
from django.db.models.utils import make_model_tuple from django.db.models.utils import make_model_tuple
...@@ -337,8 +338,13 @@ class RelatedField(Field): ...@@ -337,8 +338,13 @@ class RelatedField(Field):
rh_field.attname: getattr(obj, lh_field.attname) rh_field.attname: getattr(obj, lh_field.attname)
for lh_field, rh_field in self.related_fields for lh_field, rh_field in self.related_fields
} }
base_filter.update(self.get_extra_descriptor_filter(obj) or {}) descriptor_filter = self.get_extra_descriptor_filter(obj)
return base_filter 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 @property
def swappable_setting(self): def swappable_setting(self):
......
...@@ -166,7 +166,7 @@ class ForwardManyToOneDescriptor(object): ...@@ -166,7 +166,7 @@ class ForwardManyToOneDescriptor(object):
rel_obj = None rel_obj = None
else: else:
qs = self.get_queryset(instance=instance) 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. # Assuming the database enforces foreign keys, this won't fail.
rel_obj = qs.get() rel_obj = qs.get()
# If this is a one-to-one relation, set the reverse accessor # If this is a one-to-one relation, set the reverse accessor
......
...@@ -17,3 +17,7 @@ Bugfixes ...@@ -17,3 +17,7 @@ Bugfixes
* Added system checks for query name clashes of hidden relationships * Added system checks for query name clashes of hidden relationships
(:ticket:`26162`). (:ticket:`26162`).
* Fixed a regression for cases where
``ForeignObject.get_extra_descriptor_filter()`` returned a ``Q`` object
(:ticket:`26153`).
...@@ -44,6 +44,11 @@ class ActiveTranslationField(models.ForeignObject): ...@@ -44,6 +44,11 @@ class ActiveTranslationField(models.ForeignObject):
setattr(cls, self.name, ArticleTranslationDescriptor(self)) 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 @python_2_unicode_compatible
class Article(models.Model): class Article(models.Model):
active_translation = ActiveTranslationField( active_translation = ActiveTranslationField(
...@@ -54,6 +59,14 @@ class Article(models.Model): ...@@ -54,6 +59,14 @@ class Article(models.Model):
on_delete=models.CASCADE, on_delete=models.CASCADE,
null=True, 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() pub_date = models.DateField()
def __str__(self): def __str__(self):
......
...@@ -458,3 +458,16 @@ class TestModelCheckTests(SimpleTestCase): ...@@ -458,3 +458,16 @@ class TestModelCheckTests(SimpleTestCase):
) )
self.assertEqual(Child._meta.get_field('parent').check(from_model=Child), []) 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')
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