How do I make a field on a Django model deferred for all queries of that model?
Research
This was requested as a feature in 2014 and rejected in 2022.
Baring such a feature, the obvious idea is to make a custom manager like this:
class DeferedFieldManager(models.Manager):
use_for_related_fields = True
def __init__(self, defered_fields=[]):
super().__init__()
self.defered_fields = defered_fields
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs
).defer(*self.defered_fields)
class A(models.Model):
big_field = models.TextField(null=True)
b = models.ForeignKey(B, related_name="a_s")
objects = DeferedFieldManager(["big_field"])
class B(models.Model):
pass
class C(models.Model):
a = models.ForeignKey(A)
class D(models.Model):
a = models.OneToOneField(A)
However, while this works for A.objects.first() (direct lookups) and B.objects.first().a_s.all() (one-to-manys), it doesn't work for C.objects.first().a (many-to-ones) or D.objects.first().a (one-to-ones).
An easy way to test this is to drop the field that should be deferred from the database, and the code will only error with an OperationalError: no such column if the field is not properly deferred.
How do I make this field deferred for all ways this model is loaded (without needing to put a defer call on every query)?