{"record":{"id":"4fdbc8058f6a03f0","repo":"django/django","slug":"model-model-name-r-not-found-in-app-app-label","errorCode":null,"errorMessage":"Model %(model_name)r not found in app %(app_label)r","messagePattern":"Model %\\(model_name\\)r not found in app %\\(app_label\\)r","errorType":"http","errorClass":"Http404","httpStatus":404,"severity":"warning","filePath":"django/contrib/admindocs/views.py","lineNumber":238,"sourceCode":"            if user_has_model_view_permission(self.request.user, m._meta)\n        ]\n        return super().get_context_data(**{**kwargs, \"models\": m_list})\n\n\nclass ModelDetailView(BaseAdminDocsView):\n    template_name = \"admin_doc/model_detail.html\"\n\n    def get_context_data(self, **kwargs):\n        model_name = self.kwargs[\"model_name\"]\n        # Get the model class.\n        try:\n            app_config = apps.get_app_config(self.kwargs[\"app_label\"])\n        except LookupError:\n            raise Http404(_(\"App %(app_label)r not found\") % self.kwargs)\n        try:\n            model = app_config.get_model(model_name)\n        except LookupError:\n            raise Http404(\n                _(\"Model %(model_name)r not found in app %(app_label)r\") % self.kwargs\n            )\n\n        opts = model._meta\n        if not user_has_model_view_permission(self.request.user, opts):\n            raise PermissionDenied\n\n        title, body, metadata = utils.parse_docstring(model.__doc__)\n        title = title and utils.parse_rst(title, \"model\", _(\"model:\") + model_name)\n        body = body and utils.parse_rst(body, \"model\", _(\"model:\") + model_name)\n\n        # Gather fields/field descriptions.\n        fields = []\n        for field in opts.fields:\n            # ForeignKey is a special case since the field will actually be a\n            # descriptor that returns the other object\n            if isinstance(field, models.ForeignKey):\n                data_type = field.remote_field.model.__name__","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/django/django/blob/ae25a40be07e8a749edf526df37c93e59d4a22c9/django/contrib/admindocs/views.py#L220-L256","documentation":"Raised as Http404 by admindocs ModelDetailView when the app was found but app_config.get_model(model_name) raises LookupError, meaning no model with that name lives in the app. The model detail route resolves app then model, so a bad model_name yields a 404.","triggerScenarios":"Visiting `/admin/docs/models/<app>.<model>/` where model_name is misspelled, uses the wrong case, or refers to a model that was deleted. Python class names are case-sensitive in the URL.","commonSituations":"Typos or wrong casing in the model_name segment; a model removed by a migration but still linked; confusing the model's verbose name with its class name.","solutions":["Use the exact model class name (case-sensitive) as it appears in the app's models module.","Confirm the model still exists in that app's codebase.","Fix or remove bookmarks/links referencing the old model name."],"exampleFix":"// before: wrong casing / name\n/admin/docs/models/auth.userprofile/\n  (actual class is UserProfile, or model lives in a different app)\n\n// after: exact class name in the correct app\n/admin/docs/models/accounts.UserProfile/","handlingStrategy":"validation","validationCode":"# Verify the model exists in the app before building the doc URL.\nfrom django.apps import apps\n\ndef model_doc_url(app_label, model_name):\n    try:\n        cfg = apps.get_app_config(app_label)\n    except LookupError:\n        return None\n    if model_name not in {m.__name__ for m in cfg.get_models()}:\n        return None\n    return f\"/admin/docs/models/{app_label}.{model_name}/\"","typeGuard":null,"tryCatchPattern":"from django.http import Http404\n\ntry:\n    return model_detail_view(request, app_label, model_name)\nexcept Http404:\n    return render(request, 'docs/model_not_found.html', status=404)","preventionTips":["Derive model_name from the model class (__name__) rather than the verbose name.","Regenerate doc indexes whenever models are renamed via migrations.","Treat the URL segment as case-sensitive (it must match the Python class name)."],"tags":["admindocs","http404","configuration","models"],"analyzedSha":"ae25a40be07e8a749edf526df37c93e59d4a22c9","analyzedAt":"2026-08-06T21:46:51.801Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}