mirror of https://github.com/django/django.git
Fixed #30854 -- Fixed QuerySet.select_related() with multiple FilteredRelations.
This commit is contained in:
parent
e1ae2b0050
commit
6a75cea76a
|
@ -1,5 +1,6 @@
|
||||||
import collections
|
import collections
|
||||||
import re
|
import re
|
||||||
|
from functools import partial
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from django.core.exceptions import EmptyResultSet, FieldError
|
from django.core.exceptions import EmptyResultSet, FieldError
|
||||||
|
@ -896,6 +897,9 @@ class SQLCompiler:
|
||||||
if from_obj:
|
if from_obj:
|
||||||
f.remote_field.set_cached_value(from_obj, obj)
|
f.remote_field.set_cached_value(from_obj, obj)
|
||||||
|
|
||||||
|
def remote_setter(name, obj, from_obj):
|
||||||
|
setattr(from_obj, name, obj)
|
||||||
|
|
||||||
for name in list(requested):
|
for name in list(requested):
|
||||||
# Filtered relations work only on the topmost level.
|
# Filtered relations work only on the topmost level.
|
||||||
if cur_depth > 1:
|
if cur_depth > 1:
|
||||||
|
@ -906,15 +910,12 @@ class SQLCompiler:
|
||||||
model = join_opts.model
|
model = join_opts.model
|
||||||
alias = joins[-1]
|
alias = joins[-1]
|
||||||
from_parent = issubclass(model, opts.model) and model is not opts.model
|
from_parent = issubclass(model, opts.model) and model is not opts.model
|
||||||
|
|
||||||
def remote_setter(obj, from_obj):
|
|
||||||
setattr(from_obj, name, obj)
|
|
||||||
klass_info = {
|
klass_info = {
|
||||||
'model': model,
|
'model': model,
|
||||||
'field': f,
|
'field': f,
|
||||||
'reverse': True,
|
'reverse': True,
|
||||||
'local_setter': local_setter,
|
'local_setter': local_setter,
|
||||||
'remote_setter': remote_setter,
|
'remote_setter': partial(remote_setter, name),
|
||||||
'from_parent': from_parent,
|
'from_parent': from_parent,
|
||||||
}
|
}
|
||||||
related_klass_infos.append(klass_info)
|
related_klass_infos.append(klass_info)
|
||||||
|
|
|
@ -52,6 +52,18 @@ class FilteredRelationTests(TestCase):
|
||||||
(self.author2, self.book3, self.editor_b, self.author2),
|
(self.author2, self.book3, self.editor_b, self.author2),
|
||||||
], lambda x: (x, x.book_join, x.book_join.editor, x.book_join.author))
|
], lambda x: (x, x.book_join, x.book_join.editor, x.book_join.author))
|
||||||
|
|
||||||
|
def test_select_related_multiple(self):
|
||||||
|
qs = Book.objects.annotate(
|
||||||
|
author_join=FilteredRelation('author'),
|
||||||
|
editor_join=FilteredRelation('editor'),
|
||||||
|
).select_related('author_join', 'editor_join').order_by('pk')
|
||||||
|
self.assertQuerysetEqual(qs, [
|
||||||
|
(self.book1, self.author1, self.editor_a),
|
||||||
|
(self.book2, self.author2, self.editor_b),
|
||||||
|
(self.book3, self.author2, self.editor_b),
|
||||||
|
(self.book4, self.author1, self.editor_a),
|
||||||
|
], lambda x: (x, x.author_join, x.editor_join))
|
||||||
|
|
||||||
def test_select_related_with_empty_relation(self):
|
def test_select_related_with_empty_relation(self):
|
||||||
qs = Author.objects.annotate(
|
qs = Author.objects.annotate(
|
||||||
book_join=FilteredRelation('book', condition=Q(pk=-1)),
|
book_join=FilteredRelation('book', condition=Q(pk=-1)),
|
||||||
|
|
Loading…
Reference in New Issue