#20412: Loader that searches templates in directory tree starting by its leave. ---------------------------------+----------------------- Reporter: anonymous | Owner: nobody Type: New feature | Status: new Component: Template system | Version: 1.5 Severity: Normal | Keywords: templates Triage Stage: Unreviewed | Has patch: 0 Easy pickings: 0 | UI/UX: 0 ---------------------------------+----------------------- == Summary ==
Suggestion to implement a dynamic template loader, where the origin of the template (where it is when it is searched for rendering), counts for where it is searched. This solves the problem of template name collision, and allows for "overloading" of templates within apps. == Example of the problem == Consider the following example of app structure: {{{ root/ manage.py main/ __init__.py settings.py urls.py views.py templates/ base.html base/ header.html secondary_header.html app1/ __init__.py base_extension.html base/ secondary_header.html }}} with {{{ #base.html {% include "header.html" %} {% block secondary_header %}{% include "base/secondary_header.html" %}{% endblock %} #base_extension.html {% extends "base.html" %} {% block secondary_header %}{% include "base/secondary_header.html" %}{% endblock %} }}} My suggestion is to create a loader that: if base.html is called (in main), it includes {{{ main/base/secondary_header.html }}} if base_extension.html is called (in app1), it includes {{{ main/app1/base/secondary_header.html }}} The current implementation always finds the secondary_header.html which appears first in the INSTALLED_APPS. So if the app1 is not prepared for being added at last in INSTALLED_APPS, there can be a name collision and the app1 (which would expect its own sec_header.html) has the sec_header.html from the main. This occurs because all the current template loaders searches for the first occurrence of the template linearly in INSTALLED_APPS. == Suggestion == My suggestion is to have a loader that searches in the tree of the app calling the template with {%include%}: first searches in the templates of the app of the template (e.g. main/app1/templates/base). If none was found, it then searches in the level below (main/templates): search "main/app1/templates" if not found: search "main/templates" if not found: raise TemplateNotFound return template this search can be recursive in the app tree, and this tree can easily be retrieved from the INSTALLED_APPS. Simplifying in one sentence: the current approach searches linearly in INSTALLED_APPS. This approach searches recursively in the apps tree until either it reaches the root (template not found) or finding the template. == Discussion == There are (at least) two reasons in favor: 1. this is what django uses in most situations, the directory tree. In the current implementation, template names can collide between apps and the order of INSTALLED_APPS is important for template loading. The current implementation "suggests" that each template has to have the name of the app for avoiding collision. In this loader there is no collision with other apps, the directory tree defines the apps dependencies. 2. because it allows "overloading" of templates, as presented in the example I presented, where an app can now use the base.html (by extending it), but would still use its own secondary_header. And (at least) two reasons against: 1. the current implementation of loaders uses caching. I believe that in this implementation is more tricky, because the caching must be not only for a specific template name, but also from where it was called in the directory/apps tree. 2. All the template related code (render, search, etc) only has one argument, the template name. This change leads to major problems in adjusting the code for this case. Nevertheless, I believe the two reasons in favor are two important advantages in programing in django. -- Ticket URL: <https://code.djangoproject.com/ticket/20412> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.