During the refactor of lazy operations[1] abstract models stopped resolving
their related field model reference by themselves[2][3] in order to prevent
pending lookup pollution. This was necessary in order to warn the users about
unresolved relationships in a reliable way.
This change introduced a subtle regression[4] when an abstract model with a
lazy app relative (missing an app_label suffix) relationship is derived as
a concrete model in another application:
# app1/models.py
class Refered(models.Model):
pass
class AbstractReferent(models.Model):
refered = models.ForeignKey('Refered')
class Meta:
abtract = True
# app2/models.py
from app1.models import AbstractReferent
class Refered(models.Model):
pass
class Referent(AbstractReferent):
pass
Now that relationships defined on abstract models are only resolved on
definition of concrete subclasses the `app2.Referent.refered` points to
`app2.Refered` when it used to point to `app1.Refered`.
Here are the solutions I had in mind:
1) Refuse the temptation to guess; raise an exception on `app2.Referent`
definition about the ambigous relationship and point to resolution options.
2) As abstract models should really just be considered "placeholders for fields"
consider this new behavior the correct one. This could be considered a new
feature and a deprecation path would have to be thought of.
3) Revert to the previous behavior by converting app relative lazy relationships
to the "app_label.Model" form on `RelatedField.contribute_to_class`.
I'd favor the first option over the others because I feel like this is really
an edge case where both behaviors have merit (and a bad pratice i'd like to
prevent) but the third one is definitely the safest option.
Thanks for your feedback,
Simon
[1]
https://code.djangoproject.com/ticket/24215[2]
https://groups.google.com/d/msg/django-developers/U5pdY-WVTes/lqfv9cm9bPAJ[3]
https://github.com/django/django/pull/4115[4]
https://code.djangoproject.com/ticket/25858