Always Defer a Field in Django

Viewed 28

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)?

0 Answers
Related