﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
26481	"Add a ""strict mode"" for defer()/only() to prevent queries on unfetched field access"	Adam Johnson	nobody	"In our project at YPlan we had some highly optimized queries using `only()` to restrict the fields being fetched.

Some time later the downstream code of these queries was changed to access extra fields not in the `only()` list. This triggered the `DeferredAttribute` implicit queries to go fill in those fields with single queries, a classic N+1 queries problem.

Whilst better testing on the queries would have revealed this, I can't help but feel that it's a somewhat surprising behaviour that `only()` (and by extension, `defer()`) can bite back this badly.

I'd like some way of making `only()` and `defer()` strict, and to raise an exception on deferred fields.

Currently we've implemented this with a `patchy.patch` to insert a `raise` into `DeferredAttribute`:

{{{
from django.db.models.query_utils import DeferredAttribute

patchy.patch(DeferredAttribute.__get__, """"""\
    @@ -20,6 +20,7 @@ def __get__(self, instance, owner):
             # might be able to reuse the already loaded value. Refs #18343.
             val = self._check_parent_chain(instance, name)
             if val is None:
    +            raise AttributeError(""Deferred field '{}' fetched from database!"".format(self.field_name))
                 instance.refresh_from_db(fields=[self.field_name])
                 val = getattr(instance, self.field_name)
             data[self.field_name] = val
"""""")
}}}

I can imagine this being a Django-wide setting, or maybe per-model so it wouldn't affect third party apps so badly."	New feature	closed	Database layer (models, ORM)	dev	Normal	duplicate	only, defer	me@… Florian Apolloner	Accepted	0	0	0	0	0	0
