diff --git a/django/core/management/validation.py b/django/core/management/validation.py index c433b7fa96..bc9faae056 100644 --- a/django/core/management/validation.py +++ b/django/core/management/validation.py @@ -72,10 +72,14 @@ def get_validation_errors(outfile, app=None): # Check to see if the related field will clash with any # existing fields, m2m fields, m2m related objects or related objects if f.rel: - rel_opts = f.rel.to._meta if f.rel.to not in models.get_models(): - e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, rel_opts.object_name)) + e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, f.rel.to)) + # it is a string and we could not find the model it refers to + # so skip the next section + if isinstance(f.rel.to, (str, unicode)): + continue + rel_opts = f.rel.to._meta rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() rel_query_name = f.related_query_name() for r in rel_opts.fields: @@ -103,10 +107,14 @@ def get_validation_errors(outfile, app=None): for i, f in enumerate(opts.many_to_many): # Check to see if the related m2m field will clash with any # existing fields, m2m fields, m2m related objects or related objects - rel_opts = f.rel.to._meta if f.rel.to not in models.get_models(): - e.add(opts, "'%s' has m2m relation with model %s, which has not been installed" % (f.name, rel_opts.object_name)) + e.add(opts, "'%s' has m2m relation with model %s, which has not been installed" % (f.name, f.rel.to)) + # it is a string and we could not find the model it refers to + # so skip the next section + if isinstance(f.rel.to, (str, unicode)): + continue + rel_opts = f.rel.to._meta rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() rel_query_name = f.related_query_name() # If rel_name is none, there is no reverse accessor. diff --git a/django/db/models/options.py b/django/db/models/options.py index 23d9b04fe9..37ace0a7c1 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -152,7 +152,7 @@ class Options(object): rel_objs = [] for klass in get_models(): for f in klass._meta.fields: - if f.rel and self == f.rel.to._meta: + if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta: rel_objs.append(RelatedObject(f.rel.to, klass, f)) self._all_related_objects = rel_objs return rel_objs @@ -186,7 +186,7 @@ class Options(object): rel_objs = [] for klass in get_models(): for f in klass._meta.many_to_many: - if f.rel and self == f.rel.to._meta: + if f.rel and not isinstance(f.rel.to, str) and self == f.rel.to._meta: rel_objs.append(RelatedObject(f.rel.to, klass, f)) if app_cache_ready(): self._all_related_many_to_many_objects = rel_objs diff --git a/tests/modeltests/invalid_models/models.py b/tests/modeltests/invalid_models/models.py index b746af6dba..8a480a2381 100644 --- a/tests/modeltests/invalid_models/models.py +++ b/tests/modeltests/invalid_models/models.py @@ -108,6 +108,10 @@ class Car(models.Model): colour = models.CharField(max_length=5) model = models.ForeignKey(Model) +class MissingRelations(models.Model): + rel1 = models.ForeignKey("Rel1") + rel2 = models.ManyToManyField("Rel2") + model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "max_length" attribute. invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute. invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute. @@ -191,4 +195,6 @@ invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'm2m_4'. invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_3' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_3'. invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_4' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'm2m_4'. +invalid_models.missingrelations: 'rel2' has m2m relation with model Rel2, which has not been installed +invalid_models.missingrelations: 'rel1' has relation with model Rel1, which has not been installed """