Opened 5 years ago

Closed 5 years ago

#30874 closed Uncategorized (duplicate)

Allow disabling of lazy loading of model and related fields on querysets

Reported by: Rowan Seymour Owned by: nobody
Component: Uncategorized Version: 2.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Lazy field fetching can be super convenient but also a liability at scale. For example:

for book in Book.objects.only("id").all():
  book.author  # lazily fetches author field
  book.categories.all()  # lazily fetches related field

You might be trying to optimize your query by using only but then later you reference another field and don't realize there's now a new DB hit for every object you've loaded.

What would be really useful in situations like this to disable lazy fetching of fields and related fields, so if you haven't included them with only or select_related, the field access raises an exception.

for book in Book.objects(allow_lazy=False).only("id").all():
  book.author  # raises exception

Indicating that you need to correct the query..

for book in Book.objects(allow_lazy=False).only(''id", "author").select_related("categories").all():
  book.author
  book.categories.all()

Change History (2)

comment:1 by Simon Charette, 5 years ago

Shameless plug for a third-party library that implements just that.

The API is quite simple; it exposes a seal() method on QuerySet and Model instances that turn all fetching attempts into warnings that can be elevated to UnsealedAttributeAccess(AttributeError). We've been using it internally for a few projects so far and it does wonder to catch sneaky queries and makes field deferring less of a foot gun.

Such an API will be necessary in a future async world where lazy fetching cannot be awaited and thus must be prevented.

There's also a somewhat related approach to this problem in #28586 that suggests to automatically prefetch to one fields. I tend to agree with Anssi that this is a recipe for disaster. In my opinion it makes it impossible to determine what the ORM will do as your project evolves and more relationships are added to your models, the same kind of issues that calling select_related() without fields has.

Developer mailing list threads about both approaches

comment:2 by Simon Charette, 5 years ago

Resolution: duplicate
Status: newclosed

This is a duplicate of #22492.

Note: See TracTickets for help on using tickets.
Back to Top