I’m using manage.py runserver
on a MacOs Catalina OS as development. I have some templates that fit my built-in class based views. For example:
CuadroDeControl_detail.html LoteDeMedio_list.html TipoDeMedio_detail_tablaCuadros.html
CuadroDeControl_detail_resumen.html LoteDeMedio_list_tabla.html TipoDeMedio_list.html
CuadroDeControl_detail_tablaMetodos.html MetodoDeControl_detail.html TipoDeMedio_list_tabla.html
LoteDeMedio_confirm_delete.html MetodoDeControl_detail_resumen.html dropdown_CuadroDeControl.html
LoteDeMedio_create.html TipoDeMedio_confirm_delete.html dropwdown_CuadroDeControl.html
LoteDeMedio_detail.html TipoDeMedio_detail.html
LoteDeMedio_detail_resumen.html TipoDeMedio_detail_resumen.html
Here is an example of a working view:
class TipoDeMedioDetailView(AreaCalidadMixin, DashboardMixin, DetailView):
model = TipoDeMedio
Note that my views do not explicitly set template_name
. In my production
environment, all my views load just fine. Django’s template loader knows that the corresponding template to the view is TipoDeMedio_detail.html
However, in my production environment, which is set up with apache2
and mod_wsgi
on a Ubuntu 20.04.2 LTS x86_64 Linode VM, the template loader fails to load the template of the same view, because it searches for it in all lowercase. Here is an example:
Request Method: GET
Request URL: http://45.79.4.38/calidad/TipoDeMedio/lista
Django Version: 3.1.6
Exception Type: TemplateDoesNotExist
Exception Value:
calidad/tipodemedio_list.html
Exception Location: /home/jonatan/django-app/venv/lib/python3.8/site-packages/django/template/loader.py, line 47, in select_template
Python Executable: /home/jonatan/django-app/venv/bin/python
Python Version: 3.8.5
Python Path:
['/home/jonatan/django-app/mysite',
'/usr/lib/python38.zip',
'/usr/lib/python3.8',
'/usr/lib/python3.8/lib-dynload',
'/home/jonatan/django-app/venv/lib/python3.8/site-packages']
Server time: Mon, 21 Jun 2021 18:24:19 -0500
Template-loader postmortem
Django tried loading these templates, in this order:
Using engine django:
django.template.loaders.filesystem.Loader: /home/jonatan/django-app/mysite/templates/calidad/tipodemedio_list.html (Source does not exist)
django.template.loaders.app_directories.Loader: /home/jonatan/django-app/mysite/login/templates/calidad/tipodemedio_list.html (Source does not exist)
django.template.loaders.app_directories.Loader: /home/jonatan/django-app/venv/lib/python3.8/site-packages/django/contrib/admin/templates/calidad/tipodemedio_list.html (Source does not exist)
django.template.loaders.app_directories.Loader: /home/jonatan/django-app/venv/lib/python3.8/site-packages/django/contrib/auth/templates/calidad/tipodemedio_list.html (Source does not exist)
An easy fix is to manually specify my template_name
attribute on each of my CBV
and point to the correct case-sensitive template name (for instance TipoDeMedio_detail.html
. However, I would really like to avoid that.
I’m just trying to understand what is the root cause of the change in behavior between the environments. It just leads me to believe I will encounter similar problems in other aspects of Django’s behavior.
2
Answers
MattRowbum pointed out to me APFS isn't case sensitive. I consider this sufficient explanation for the change in behavior.
The default Apple File System (APFS) is not case sensitive. This means that during development on your Mac, Django was able to find templates even if the filenames used incorrect case.
Now that you have moved to Ubuntu, it uses a case-sensitive file system by default. Django is not able to find the templates if the case is wrong.
Note that the Django docs for class-based generic views state:
The preferable solution is to rename your templates using lowercase.