get_for_models methods always return the
ContentType of the concrete class of a proxy model. This behaviour is causing
GenericForeignKey to save the concrete class of proxy model and creates inconsistencies in the
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
app_label = 'app'
proxy = True
ct_get_for_model = ContentType.objects.get_for_model(Worker)
ct_natural_key = ContentType.objects.get_by_natural_key('app', 'worker')
assert ct_natural_key == ct_get_for_model # raises AssertionError
I don't know if it was a design decision (IHMO it's a mistake and a bug) to do so but changing it now would introduce a small backward compatibility issue for any app relying on
get_for_model directly or indirectly through the use of `GenericForeignKey' since they would now benefit from getting the exact ct they were referencing.
If I'm not mistaken, by looking at regressiontests.defer_regress.tests.DeferRegressionTest and #10738, I assume this was introduced by r10523 to make sure deferred models are handled correctly by
get_for_model. Checks for proxy reversing should be made against
model._defered and not `model._meta.proxy'.
A discussion recently emerged of #11154 (which is caused by this behaviour) suggesting to either remove the proxy following routine of
get_for_model(s?) or to allow passing a flag (
follow_proxy) to opt-in for the correct behaviour.
I'm attaching a simple patch that only replaces the checks in
_get_opts (and automatically fixes #11154) and I'll be marking the ticket as 'DDN' since it involves a small backward compatibility issue that requires feedbac.