Loading django/db/models/fields/related.py +8 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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): Loading django/db/models/fields/related_descriptors.py +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading docs/releases/1.9.3.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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`). tests/foreign_object/models/article.py +13 −0 Original line number Diff line number Diff line Loading @@ -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( Loading @@ -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): Loading tests/foreign_object/tests.py +13 −0 Original line number Diff line number Diff line Loading @@ -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') Loading
django/db/models/fields/related.py +8 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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): Loading
django/db/models/fields/related_descriptors.py +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
docs/releases/1.9.3.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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`).
tests/foreign_object/models/article.py +13 −0 Original line number Diff line number Diff line Loading @@ -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( Loading @@ -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): Loading
tests/foreign_object/tests.py +13 −0 Original line number Diff line number Diff line Loading @@ -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')