#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.


Reply via email to