This is great, but one remaining issue: If the related objects lookups always use the corresponding manager, then this:
> article_obj.reporter would be equivalent to: > Reporter.objects.get(pk=article_obj.id) That can throw a Reporter.DoesNotExist exception, which might not just be corner case i.e. it might be perfectly allowable in your model to have articles with a null reporter. In the proposal (the original one at least), article_obj.reporter.id wouldn't do a DB lookup, so .reporter must be lazy, which kind of makes things worse - you can use reporter.id, but reporter.name will blow up on you. There are two use cases AFAICS: - in view code, you want to know immediately if the object doesn't exist, and not have to do some silly tricks to get the lazy object to initialise from the db and throw any appropriate exceptions - in template code, you might want: {% if article_obj.reporter %} Written by {{ article_obj.reporter.name }} {% endif %} Can we do both these? Perhaps a .lazyget() method on objects will help - foreign key fields always translate into that. The __get__() descriptor on the article_obj.reporter always does a .lazyget(), which returns a lazy object which only has the id set. This way we can still do article_obj.reporter.id without DB access. The lazy object needs a __nonzero__ method that will first initialise it, and if it fails to initialise it then return false, otherwise true. .get(), on the other hand, doesn't get a lazy object, but immediately throws exceptions if it's not there. Think that covers it - are there any holes? Luke