django/django · warning · Http404
Model %(model_name)r not found in app %(app_label)r
Error message
Model %(model_name)r not found in app %(app_label)r
What it means
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.
Source
Thrown at django/contrib/admindocs/views.py:238
if user_has_model_view_permission(self.request.user, m._meta)
]
return super().get_context_data(**{**kwargs, "models": m_list})
class ModelDetailView(BaseAdminDocsView):
template_name = "admin_doc/model_detail.html"
def get_context_data(self, **kwargs):
model_name = self.kwargs["model_name"]
# Get the model class.
try:
app_config = apps.get_app_config(self.kwargs["app_label"])
except LookupError:
raise Http404(_("App %(app_label)r not found") % self.kwargs)
try:
model = app_config.get_model(model_name)
except LookupError:
raise Http404(
_("Model %(model_name)r not found in app %(app_label)r") % self.kwargs
)
opts = model._meta
if not user_has_model_view_permission(self.request.user, opts):
raise PermissionDenied
title, body, metadata = utils.parse_docstring(model.__doc__)
title = title and utils.parse_rst(title, "model", _("model:") + model_name)
body = body and utils.parse_rst(body, "model", _("model:") + model_name)
# Gather fields/field descriptions.
fields = []
for field in opts.fields:
# ForeignKey is a special case since the field will actually be a
# descriptor that returns the other object
if isinstance(field, models.ForeignKey):
data_type = field.remote_field.model.__name__View on GitHub (pinned to ae25a40be0)
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.
Example fix
// before: wrong casing / name /admin/docs/models/auth.userprofile/ (actual class is UserProfile, or model lives in a different app) // after: exact class name in the correct app /admin/docs/models/accounts.UserProfile/
Defensive patterns
Strategy: validation
Validate before calling
# Verify the model exists in the app before building the doc URL.
from django.apps import apps
def model_doc_url(app_label, model_name):
try:
cfg = apps.get_app_config(app_label)
except LookupError:
return None
if model_name not in {m.__name__ for m in cfg.get_models()}:
return None
return f"/admin/docs/models/{app_label}.{model_name}/" Try / catch
from django.http import Http404
try:
return model_detail_view(request, app_label, model_name)
except Http404:
return render(request, 'docs/model_not_found.html', status=404) Prevention
- 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).
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- App %(app_label)r not found
- %s must have search_fields for the autocomplete_view.
- The XView middleware requires authentication middleware to b
- %(ct_name)s objects don’t have a get_absolute_url() method
- You must supply a valid app label and module name. Got "%s.%
AI-assisted analysis of django/django@ae25a40be0 (2026-08-06).
Data as JSON: /api/errors/4fdbc8058f6a03f0.
Report an issue: GitHub.