为什么 Django 模板加载器在生产中区分大小写但在开发中不区分大小写

Why Django template loader is case-sensitive in production but not in development

我在 MacOs Catalina OS 上使用 manage.py runserver 作为开发。我有一些模板适合我基于 class 的内置视图。例如:

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

这是工作视图的示例:

class TipoDeMedioDetailView(AreaCalidadMixin, DashboardMixin,  DetailView):
         model = TipoDeMedio

请注意,我的观点并未明确设置 template_name。在我的制作中 环境,我所有的观点都加载得很好。 Django的模板加载器知道视图对应的模板是TipoDeMedio_detail.html

但是,在我的生产环境中,在 Ubuntu 20.04.2 LTS x86_64 Linode VM 上设置了 apache2mod_wsgi,模板加载器无法加载同一视图的模板,因为它以全小写形式搜索它。这是一个例子:

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)

一个简单的解决方法是在我的每个 CBV 上手动指定我的 template_name 属性并指向正确的区分大小写的模板名称(例如 TipoDeMedio_detail.html。但是,我真的很想避免这种情况。

我只是想了解环境之间行为变化的根本原因是什么。它只是让我相信我会在 Django 行为的其他方面遇到类似的问题。

默认的 Apple 文件系统 (APFS) 不区分大小写。这意味着在 Mac 的开发过程中,即使文件名使用了不正确的大小写,Django 也能够找到模板。

现在您已经移动到 Ubuntu,它默认使用区分大小写的文件系统。如果大小写错误,Django 将无法找到模板。

请注意 Django docs for class-based generic views 状态:

... in the absence of an explicit template Django will infer one from the object’s name ... is the lowercased version of the model’s name.

更好的解决方案是使用小写重命名模板。

MattRowbum 向我指出 APFS 不区分大小写。我认为这足以解释行为的变化。