Python › Descriptors & Properties

How do you implement a descriptor-based ORM-style field that lazily loads related data only when actually accessed?

Advanced

Answer

Implement __get__ to check if the related data has already been fetched and cached on the instance; if not, perform the (potentially expensive) lookup, cache the result, and return it — this pattern underlies 'lazy loading' relationship fields in ORMs like Django and SQLAlchemy, deferring expensive queries until genuinely needed.
class LazyForeignKey:
    def __set_name__(self, owner, name):
        self.cache_name = f"_{name}_cache"
    def __get__(self, instance, owner):
        if instance is None:
            return self
        if not hasattr(instance, self.cache_name):
            related_id = getattr(instance, f"{self.name}_id")
            setattr(instance, self.cache_name, fetch_related_object(related_id))  # lazy DB query
        return getattr(instance, self.cache_name)
Real-world example Implementing a lazy-loaded relationship field (like Django's ForeignKey) that only queries the database when the related object is actually accessed.

Common follow-ups: What's the downside (N+1 query risk) of this lazy-loading pattern when accessed in a loop over many instances?