Code

Opened 4 years ago

Closed 3 years ago

#13144 closed Uncategorized (wontfix)

django.template.loaders.app_directories.Loader should look in template subdirectory of current view's application first

Reported by: betawarz Owned by: nobody
Component: Template system Version: 1.1
Severity: Normal Keywords: Loader, Template, app_directories
Cc: hofbauer@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The django.template.loaders.app_directories.Loader template loader needs to look for the templates subdirectory in the current view's application directory first. Currently, it looks through templates subdirectories in the order that they appear in INSTALLED_APPS. This results in issues when multiple applications all use their own 'index.html', or other matching template names.

I would almost argue that when using django.template.loaders.app_directories.Loader it should only look in the current view's application directory.

As it stands, a user has to create a unique subdirectory inside of the templates subdirectory of each application so that the loader can differentiate while traversing through the paths. This removes a lot of the intended results of this type of template loader, in my opinion.

Attachments (0)

Change History (5)

comment:1 in reply to: ↑ description Changed 4 years ago by betawarz

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Unless I'm doing this wrong. :P

comment:2 Changed 4 years ago by carljm

  • Resolution set to wontfix
  • Status changed from new to closed

Yes you're doing this wrong.

For one thing, the template system has no idea what the "current app" might be.

It's a _feature_ that the template hierarchy is always consistent and always rooted at the same place with the same lookup order: the name "index.html" is always a reliable reference to the same template file, no matter where it is referenced from. And it's a good thing for one app to be able to override templates from another app; this gives the template system all kinds of flexibility it wouldn't have otherwise.

The correct solution is, as you intuit, to generally place each app's templates in a subdirectory named for that app.

comment:3 Changed 3 years ago by hofbauer@…

  • Easy pickings unset
  • Resolution wontfix deleted
  • Severity set to Normal
  • Status changed from closed to reopened
  • Type set to Uncategorized
  • UI/UX unset

I must say I cannot quite follow carjm's reasoning and agree with initial request (in fact I landed on this page expecting this behavior).

Carljm says "it's a good thing for one app to be able to override templates from another app;" - but given that precedence is given by (from app-perspective random) order in INSTALLED_APPS, changing order of apps in INSTALLED_APPS changes what templates are used.

The documentation says: "This means you can store templates with your individual apps. This also makes it easy to distribute Django apps with default templates." But unless I create another subdirectory in the app's template dir, I am subject to templates of other apps being used instead of the intended one, as soon as there are name collisions.

Assume one project with several apps developed by different people.
The most logical structure for me would be to have a structure like

mysite
|
|-- app1
|    |
|    - templates (specific to app1)
|
|-- app2
|    |
|    - templates (specific to app2)
|
|-- templates (generic ones)

I would set

TEMPLATE_DIRS = ( '.../mysite/templates')

and switch loader order to

TEMPLATE_LOADERS = (
    'django.template.loaders.app_directories.Loader',
    'django.template.loaders.filesystem.Loader',
)

The expected behaviour would be that I could have templates with same name in both the app's template directory and the generic directory, and the app's directory template would override the generic template. Currently however this is not possible since also another app might have a template with the same name and I unintentinally end up with that one.

Given current implementation I do not understand what the app_directories.Loader could (reliably) be used for.

comment:4 Changed 3 years ago by hofbauer@…

  • Cc hofbauer@… added

comment:5 Changed 3 years ago by carljm

  • Resolution set to wontfix
  • Status changed from reopened to closed

The current implementation offers maximum flexibility to the final integrator of the apps (the project developer), including the option of having an app that builds on top of and overrides templates from another third-party app. TEMPLATE_DIRS templates usually should override app templates, not the other way around, as its the developer of the site who knows what they really need for their project, not the developer of a reusable app, who is at best providing suggested or default templates for their app. The cost of this flexibility is that you should explicitly namespace your apps' templates (app1/templates/app1/...) to avoid accidental name collisions. Doing so obviates all your concerns, and the extra directory layer is not onerous. This system is widely used, and despite your confusion, it works very well for many Django users and it is not going to change.

As documented in the contributing documentation, please do not reopen bugs closed by a core developer. Trac is not a good place for discussion or debate, please post to the django-developers mailing list instead if you would like to discuss it further.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.