Repository: django/django

Issue:
# Fixed #36804 -- Fixed admin system check crash for missing models.

…f AdminSite

There was an issue while raising the `NotRegistered` exception in get_model_admin when a string was passed to it instead of a model class. Fixed it by checking with `isinstance`. Added a test for this too.

#### Trac ticket number
<!-- Replace XXXXX with the corresponding Trac ticket number, or delete the line and write "N/A" if this is a trivial PR. -->

ticket-36804

#### Branch description
Handles a string passed to the `get_model_admin` method of the `AdminSite` class (in cases where the `to` field of a `ForeignKey` is specified using a model name instead of a model class.

#### Checklist
- [x] This PR targets the `main` branch. <!-- Backports will be evaluated and done by mergers, when necessary. -->
- [x] The commit message is written in past tense, mentions the ticket number, and ends with a period.
- [x] I have checked the "Has patch" ticket flag in the Trac system.
- [x] I have added or updated relevant tests.
- [ ] I have added or updated relevant docs, including release notes if applicable.
- [ ] I have attached screenshots in both light and dark modes for any UI changes.


Implementation patch:
diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py
index 10257a54bf89..d14515e8a424 100644
--- a/django/contrib/admin/checks.py
+++ b/django/contrib/admin/checks.py
@@ -236,14 +236,20 @@ def _check_autocomplete_fields_item(self, obj, field_name, label):
                     id="admin.E038",
                 )
             try:
+                if isinstance(field.remote_field.model, str):
+                    raise NotRegistered
                 related_admin = obj.admin_site.get_model_admin(field.remote_field.model)
             except NotRegistered:
+                # field.remote_field.model could be a string or a class.
+                remote_model = getattr(
+                    field.remote_field.model, "__name__", field.remote_field.model
+                )
                 return [
                     checks.Error(
                         'An admin for model "%s" has to be registered '
                         "to be referenced by %s.autocomplete_fields."
                         % (
-                            field.remote_field.model.__name__,
+                            remote_model,
                             type(obj).__name__,
                         ),
                         obj=obj.__class__,


Test patch:
diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py
index fbd63abfbf15..c493148eb9cf 100644
--- a/tests/modeladmin/test_checks.py
+++ b/tests/modeladmin/test_checks.py
@@ -1724,6 +1724,28 @@ class Admin(ModelAdmin):
             invalid_obj=Admin,
         )
 
+    @isolate_apps("modeladmin")
+    def test_autocomplete_e039_unresolved_model(self):
+        class UnresolvedForeignKeyModel(models.Model):
+            unresolved = models.ForeignKey("missing.Model", models.CASCADE)
+
+            class Meta:
+                app_label = "modeladmin"
+
+        class Admin(ModelAdmin):
+            autocomplete_fields = ("unresolved",)
+
+        self.assertIsInvalid(
+            Admin,
+            UnresolvedForeignKeyModel,
+            msg=(
+                'An admin for model "missing.Model" has to be registered '
+                "to be referenced by Admin.autocomplete_fields."
+            ),
+            id="admin.E039",
+            invalid_obj=Admin,
+        )
+
     def test_autocomplete_e040(self):
         class NoSearchFieldsAdmin(ModelAdmin):
             pass