The solution is to have a separate queryset factory on a manager get_full_query_set that can be overridden but is required to return all records. Old get_query_set normally just calls get_full_query_set and can be overridden in a usual way. This part is backwards compatible. Also managers acquire a new method get_full which works like get but explicitly calls get_full_query_set. This method is used to access single related (parent) objects. This will require users who was overriding get to override get_full instead if they wish to ensure that default filtering doesn't get in the way. This is as backwards incompatible as was after #7666 that has broken overriding of get but provides a new API to overcome this.

Incidentally, I was also thinking about setting some state to a Manager before calling get. But I've decided against it because:

when the flag is set permanently to True it binds get to behave only in a single fashion, but the point of #7666 is that it should have different behavior depending on if it is called for parent relation or directly with Model.objects.get

switching the flag dynamically creates a possibility to forget to do it and, worse, introduces a transient state into process which will break things if Manager.get calls other functions that also indirectly call Manager.get counting on different state

a stack of states might fix previous issue but this solution is really overcomplicated and ugly

This is why I've just made an explicit full_get that can be called separately from get. And two queryset factories are needed because queryset creation in general may be customized in many different ways but filtering is the only type of customization that we care about when accessing parent objects. Thus splitting it into a separate point.

(In [8212]) Fixed #7904: added support for a "use_for_related_fields" property on managers. If True, the manager will be used for related object lookups instead of the "bare" QuerySet introduced bu [8107]. Patch from Justin Bronn.