Tai Lee
unread,Mar 9, 2011, 7:52:37 PM3/9/11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Django developers
I have a generic app which includes base templates (for HTML
documents, emails, etc.) and also template tags that render a template
(for form fields, pagination forms/links, filter forms/links, etc.)
Sometimes I have a project that has several other apps installed which
both use the base templates and template tags from the generic app.
Sometimes I need to be able to override the base templates or the
templates rendered by template tags, but only for a single app,
without affecting the other apps.
Currently I believe the only way to override these templates for a
single app only is to pass a list of template names instead of a
single template name to a loader in the views for that app, with the
first template name having a prefix of the current app. But this only
works in my views and my template tags (not with built in template
tags like `extends` and `include`).
I could also duplicate these templates and put them in one of my
TEMPLATE_DIRS, but this would affect all apps within my project.
I would like to propose a few things to make this easier (or possible
at all).
Currently, the `process_view()` method of request middleware is passed
the request, the view function, args and kwargs, which are obtained by
the `resolve()` method, which also returns `url_name`, `app_name` and
`namespace`.
If `namespace` was also passed to `process_view()`, it would be
trivial for users to create a middleware that adds `namespace` to
request objects (or Django could ship with one), which could then
easily be passed through to ``Context`, `RequestContext` and
`TemplateResponse` as `current_app` in the user's views without having
to look it up again (which Django already did with `resolve()`) or
hard code it.
`RequestContext` and `TemplateResponse` could even use
`request.namespace` (if set) as a default for `current_app` (if not
explicitly passed as an argument).
Currently the docs recommend that users pass `current_app` to
`Context`, `RequestContext` and `TemplateResponse`. Why not just do it
for them by default? I can't think of a use case where users would
want to pass a `current_app` that does not match the `namespace` of
the requested URL, but even if they did that would also still be
possible.
If template loaders also accepted a `current_app` argument, which
Django could pass automatically (if set on the context) when using
built in template tags (e.g. `extends`, `include`, etc.), then users
could write their own template loaders that looked for templates in a
folder prefixed with `current_app` first. For example, if
`current_app` on my context is "myapp1" and I do `{% extends "otherapp/
base.html" %}`, it could try to load `['myapp1/otherapp/base.html',
'otherapp/base.html']`.
To summarise:
Ideally I would like Django to automatically add `namespace` (or
`current_app`) to request objects via middleware (and give
`process_view()` access to other attributes returned by `resolve()`),
I would like `RequestContext` and `TemplateResponse` to automatically
use this (if set on `request`, and if `current_app` is not explicitly
passed in as an argument), and I would like built in template tags
like `extends` and `include` to automatically pass `current_app` from
the context (if set) to the template loader(s).
Does anyone have any reason why such a thing would be a bad idea and
likely to be rejected, before I start working on a patch?
If we don't want this to be the default behaviour, the very least I
think we would need to make this feature possible is to allow
`current_app` to be passed as an argument to template loaders and for
built in template tags like `extends` and `include` to pass the
`current_app` (if set on the context).
I can already create a middleware to add `namespace` to `request` (by
resolving `request.path` a second time, not ideal but possible). I can
already add `current_app` to all my `RequestContext` and
`TemplateResponse` objects (but it'd be nicer if Django did it for
me). I can create my own helper function that will return a template
name for the current app, if it exists in the current app's template
folder, given a template name for another app. But I can't create a
template loader that built in template tags like `extends` and
`include` would use to look for templates from the current app's
templates folder. At least, not without resorting to storing the
request in thread locals or something.
Cheers.
Tai.