Fixed #21204 -- Tracked field deferrals by field instead of models.

This ensures field deferral works properly when a model is involved
more than once in the same query with a distinct deferral mask.
This commit is contained in:
Simon Charette 2022-08-18 12:30:20 -04:00 committed by Mariusz Felisiak
parent 5d12650ed9
commit b3db6c8dcb
6 changed files with 121 additions and 126 deletions

View file

@ -259,7 +259,7 @@ class RegisterLookupMixin:
cls._clear_cached_lookups()
def select_related_descend(field, restricted, requested, load_fields, reverse=False):
def select_related_descend(field, restricted, requested, select_mask, reverse=False):
"""
Return True if this field should be used to descend deeper for
select_related() purposes. Used by both the query construction code
@ -271,7 +271,7 @@ def select_related_descend(field, restricted, requested, load_fields, reverse=Fa
* restricted - a boolean field, indicating if the field list has been
manually restricted using a requested clause)
* requested - The select_related() dictionary.
* load_fields - the set of fields to be loaded on this model
* select_mask - the dictionary of selected fields.
* reverse - boolean, True if we are checking a reverse select related
"""
if not field.remote_field:
@ -287,9 +287,9 @@ def select_related_descend(field, restricted, requested, load_fields, reverse=Fa
return False
if (
restricted
and load_fields
and select_mask
and field.name in requested
and field.attname not in load_fields
and field not in select_mask
):
raise FieldError(
f"Field {field.model._meta.object_name}.{field.name} cannot be both "