Understaning Django's template automatic search/file system - templates

From the tutorial online https://docs.djangoproject.com/en/dev/intro/tutorial02/#customizing-your-project-s-templates it states to place user templates into a directory like so:
/project/app/templates/app/example.html
But when the automatic template loader searches it looks in:
/project/app/templates/
Likewise when you try to load a default template that is located at:
/Python27/Lib/site-packages/django/contrib/admin/templates/admin/base.html
It will search in:
/Python27/Lib/site-packages/django/contrib/admin/templates/
Am I missing something here? I have not defined any TEMPLATE_DIRS because I want the default system to operate like the tutorial says.
UPDATE/SOLUTION:
The reason I was confused is that you put templates that are native to the app in
/project/app/templates
and then put non-native templates in
/project/app/templates/non-native_app-name
And also when using {% extends "template.html" %} you must place app name before template like so {% extends "app-name/template.html" %}
Correct me if I am wrong here... Thanks for the help

If you have django.template.loaders.app_directories.Loader in your TEMPLATE_LOADERS settings, this actually should be in your settings by default:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
Then, django will search through templates directory in each of your apps, quote from docs:
Loads templates from Django apps on the filesystem. For each app in
INSTALLED_APPS, the loader looks for a templates subdirectory. If the
directory exists, Django looks for templates in there.
This means you can store templates with your individual apps. This
also makes it easy to distribute Django apps with default templates.

if u read django's source, you can find code in django.template.loaders.py .
def find_template(name, dirs=None):
# Calculate template_source_loaders the first time the function is executed
# because putting this logic in the module-level namespace may cause
# circular import errors. See Django ticket #1292.
global template_source_loaders
if template_source_loaders is None:
loaders = []
for loader_name in settings.TEMPLATE_LOADERS:
loader = find_template_loader(loader_name)
if loader is not None:
loaders.append(loader)
template_source_loaders = tuple(loaders)
for loader in template_source_loaders:
try:
source, display_name = loader(name, dirs)
return (source, make_origin(display_name, loader, name, dirs))
except TemplateDoesNotExist:
pass
raise TemplateDoesNotExist(name)

Related

How to get the name of current app within a template?

What's the simplest way to access the name of the current app within template code?
Alternatively, what's the simplest way to define a template variable to hold the name of the current app?
(The goal here is to minimize the number of places I need to edit if I rename an app.)
Since Django 1.5 there is a "resolver_match" attribute on the request object.
https://docs.djangoproject.com/en/dev/ref/request-response/
This contains the matched url configuration including "app_name", "namespace", etc.
https://docs.djangoproject.com/en/2.2/ref/urlresolvers/#django.urls.ResolverMatch
The only caveat is that it is not populated until after the first middleware passthrough, so is not available in process_request functions of middleware. However it is available in middleware process_view, views, and context processors. Also, seems like resolver_match is not populated in error handlers.
Example context processor to make available in all templates:
def resolver_context_processor(request):
return {
'app_name': request.resolver_match.app_name,
'namespace': request.resolver_match.namespace,
'url_name': request.resolver_match.url_name
}
There's a way to obtain an app name for a current request.
First, in your project's urls.py, considering your app is called 'main':
#urls.py
url(r'^', include('main.urls', app_name="main")),
Then, a context processsor:
#main/contexts.py
from django.core.urlresolvers import resolve
def appname(request):
return {'appname': resolve(request.path).app_name}
Don't forget to enable it in your settings:
#settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.request",
"main.contexts.appname",)
You can use it in your template like any other variable: {{ appname }}.

Django View Preprocessing

Just looking for some guidance here on how to implement this concept in "Django fashion".
I am using dbsettings to define site level variables. On each request I want to check one of my site level variables and render a different response based on the value of that variable.
Now I realize I could easily accomplish this just by adding a simple if statement in each of my view functions, but I thought there may be a way I could apply this at a higher level?
Let me know if there is a way to "globalize" this functionality across all requests. Thanks.
Actually, what you really probably want is middleware, if the setting is going to affect the template that's chosen in the first place, or substantially affect the response. It is a good deal more flexible than using a template context processor, which is more appropriate if you simply want to add a couple variables to your context.
You create a middleware.py in your app, which might contain something like:
from django.conf import settings
class MyMiddleware(object):
def process_request(self, request):
request.my_app_setting = settings.MY_APP_SETTING
Don't forget to add your class to your MIDDLEWARE_CLASSES setting.
You can use custom template context processors for passing "global" context to your views.
To accomplish this, create a new contextprocessors.py somewhere in your application with code similar to the example below (all it has to do is return a dict). Then add the path to the file with the function in the TEMPLATE_CONTEXT_PROCESSORS tuple in your settings.py (ie: yourapp.contextprocessors.resource_urls).
from django.conf import settings
def resource_urls(request):
"""Passes global values to templates."""
return dict(
TIME_ZONE = settings.TIME_ZONE,
)
Now you can refer to these keys in your templates as expected: {{ TIME_ZONE }}.

Django: Define a template context processor in all templates without creating a new view

I need to get an environment variable (ex: Mixpanel_Token) in all my templates, and without creating a new view in Django.
From what I read on SO, I should use a Template Context Processor.
The context_processor is defined in context_processors.py file:
from django.conf import settings
def settings_mixpanel(request):
ctx = {
"MIXPANEL_TOKEN": settings.MIXPANEL_TOKEN,
}
return ctx
In my settings.py file:
TEMPLATE_CONTEXT_PROCESSORS = (
'utils.context_processors.settings_mixpanel',
)
The issue I encounter is how to define MIXPANEL_TOKEN as a context variable in all my templates, given that all my views are already created in Django.
I don't want to recreate a view like the below one, using render_to_response function:
def index(request):
return render_to_response("index.html", {},context_instance=RequestContext(request))
You don't need to do anything special. As long as your template is rendered with RequestContext, you'll be able to access your variable with {{ MIXPANEL_TOKEN }}.
It is quite easy and straightforward: the context processors are called by RequestContext(...). If you do not use RequestContext(...), the context processors will not be used and will therefore not be of any value. You do not necessarily need to use render_to_response, but RequestContext is a must. Like it or not, that is how Django works. But from my personal view, changing your existing views to use RequestContext is not really a big thing, is it?
since Django 1.8 registring of custom context processor for templates happens via: TEMPLATES-> OPTIONS -> context_processors see here for reference: https://docs.djangoproject.com/en/1.10/ref/templates/upgrading/#the-templates-settings

how to pass variables to templates only for some applications

I have a django project, with a lot of applications. Now i need to add some variables to the context dictionary only for some applications.Does django provide any option to achieve this?
I know decorator can be helpful.Is there any other way,like a middleware / context processor that runs automatically but only for specific applications.
A context processor like this can do what you need:
from django.core.urlresolvers import resolve
def app_var(request):
if resolve(request.path).app_name == 'YOUR_APP_NAME':
return {'CUSTOM_VAR': 'VALUE'}
return {}
to install the context processor, put the code in any file you like, and add a entry referencing (e.g. 'folder.file.app_var') it in the CONTEXT_PROCESSORS in your settings.py.

Django - Global variable, Should I use Template context processor?

my question is:
Should I use Template context processor for global variable like category list ?
I have globs.py
from news.models import Category
def globs(request):
cats = Category.objects.all()
return {'cats': cats}
and in settings.py
TEMPLATE_CONTEXT_PROCESSORS = ("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"globs.globs",)
And when I use in template 'cats' it works fine on developer server.
On my hosting I have a problem:
Error importing request processor module globs: "No module named globs"
Can I use something else for global variables?
globs.py needs to be in your importable path on your hosting server. You could move it to your news directory and use "news.globs.globs" in TEMPLATE_CONTEXT_PROCESSORS.