Slight modification to default `__repr__` for models?

I was looking into an old issue about making DoesNotExist errors nicer (Fixed #20278 -- ensured .get() exceptions do not recurse infinitely · django/django@266c0bb · GitHub) which was reverted due to an infinite recursion, and I realized that the reason this problem occurs is because of another issue that I always patch in my projects: the default __repr__ on models calls __str__.

Current implementation:

    def __repr__(self):
        return "<%s: %s>" % (self.__class__.__name__, self)

In all my projects I always have a common base class for my models that contain:

    def __repr__(self):
        return f'<{self.__class__.__name__} pk={self.pk}>'

With this in place, the repr of an object won’t infinitely recurse by default, which means we can make DoesNotExist nicer.

A side not on this is that it’s also the case that the fix for DoesNotExist being reverted was because the error can end up in an infinite loop. But that’s also true for MultipleObjectsReturned. So logically we should either make DoesNotExist work or make MultipleObjectsReturned worse. I prefer the first :stuck_out_tongue:

2 Likes