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

This commit is contained in:
Anssi Kääriäinen 2016-01-29 11:03:47 +02:00 committed by Tim Graham
parent 1d86d4c72b
commit 353aecbf8c
5 changed files with 39 additions and 3 deletions

View File

@ -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):

View File

@ -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

View File

@ -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`).

View File

@ -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):

View File

@ -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')