Django templates lookup order - django

I'm writing an app, that uses django-floppyforms. Also, my app provides the default twitter bootstrap skin, so i have customized floppyforms templates im my app to make them bootstrap alike. I put floppyforms/{layouts, rows}/bootstrap into my app's templates directory. But it does not work: django won't use them. So, i don't want to enforce end user to put customized templates into his project, in fact, i want to point django to take my local floppyforms templates when it renders in-app content. I just want to make my app standalone without any unhandy depencies.
UPDATE
Now i'm having the similar troubles with django-admintools-bootstrap and Django 1.5.1. It was added before admin_tools in INSTALLED_APPS, but there's no effect. Also it won't collect static for django-admintools-bootstrap. In other similar projects using this two packages and Django 1.4, all works fine. Also, i've checked the release notes for Django 1.5 for template lookup order changes and found nothing about it.

Updated answer:
As of Django 1.8, TEMPLATE_DIRS and TEMPLATE_LOADERS are deprecated and replaced by TEMPLATES.
An example of TEMPLATES can be:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
# 'loaders': [
# 'django.template.loaders.filesystem.Loader',
# 'django.template.loaders.app_directories.Loader',
# ],
'debug': True,
},
},
]
The template lookup order is by dictated by the following:
Essentialy the most important place is the loaders option of the OPTIONS. If this is defined, it requires that APP_DIRS is not set and follows any explicit order there.
If no loaders, and if any DIRS defined, these have priority as the filesystem loader.
If no loaders, and APP_DIRS is defined, these have second priority over DIRS.
The above are not explicitly documented, but can easily be deducted by the existing documentation and maybe after some experiments.

If they are not in apps template directory, add absolute path of your templates directories in TEMPLATE_DIRS settings.
These directories will be searched in order, so add them in front.
If they are in apps directory, you may want to put 'django.template.loaders.app_directories.Loader' ahead of anyone in TEMPLATE_LOADERS setting.
Also, check how you are using template names while specifying templates. You should use as 'floppyforms/layouts/bootstrap/template1.html'.
More info at template loaders

Related

Django - How to navigate between multiple apps

I'm a beginner in Django and don't understand how the templates "dirs" in setup.py works
In my project directory, I have 2 apps. I want to reach them via a navigation bar.
In the Navigation bar, I have "Home" "Manipulation" "Visualization"
I can reach Home and Manipulation page, but when I try to reach the Visualization page, the browser shows me the Manipulation page again.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
os.path.join(BASE_DIR, 'manipulation/templates/manipulation'),
os.path.join(BASE_DIR, 'visualization/templates/visualization'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Somebody can help me please?
Thank you very much
In Dirs : [], when I swap the order and put the "Visualization" path before the "Manipulation" path, I get the Visualization page instead of the Manipulation page
if you have
'APP_DIRS' = True,
django will automatically look for templates in all app_name/templates/ folders
point to templates always as "app_name/template_name.html"
(which will then point to "app_name/templates/app_name/template_name.html")
store the templates as app_name/templates/app_name/templates_name.html"
That way you can have an individual e.g. home.html in each app without conflicts.
in 'DIRS' you should only add directories that you want to add outside the apps systematic. Currently you are overwriting the normal search in you your app folders and together with a missing "app_name/" in your "/app_name/template_name.html" you get the behavior that you describe

How to override external app template in Django?

I tried overriding a django-recaptcha template without any luck. What am I doing wrong?
I am aware of Override templates of external app in Django, but it is outdated. Thanks!
django-recaptcha file structure
Lib/
--site-packages/
----captcha/
------templates/
--------captcha/
----------includes/
------------js_v2_checkbox.html
my project file structure
project/
----templates/
--------captcha/
------------includes/
----------------js_v2_checkbox.html
settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
You have two options:
(1) In your settings, rearrange INSTALLED_APPS as follows:
INSTALLED_APPS = [
...
'project',
...
'captcha',
...
]
since the template loader will look in the app’s templates directory following the order specified by INSTALLED_APPS, you're template will be found first.
or
(2) List project's templates folder in TEMPLATES[0]['DIRS'] as follows:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
...
},
]
Since, DIRS is searched before APP_DIRS, you're template will be found first.
References:
https://docs.djangoproject.com/en/3.0/howto/overriding-templates/
Another possible solution
I notice now that captcha/includes/js_v2_checkbox.html is included by captcha/widget_v2_checkbox.html.
I'm not sure about what happens exactly when widget_v2_checkbox.html is loaded from captcha module ... so I would duplicate the "including" widget_v2_checkbox.html as well into your project's templates folder.
You might also decide to copy the full "templates/captcha" folder contents into you project, for consistency.
Just keep an eye on possibile future changes of those templates when upgrading the captcha module.
Can I see the order of your INSTALLED_APPS? It could be that you are rendering django-recaptcha captcha templates before you render your own templates. To fix this you could move the the external app captcha last in the INSTALLED_APPS list.

Load template based on domain

There are two sites with different domains (first_example.com, second_example.com). They have a common database and common logic.
The task is what needs to be done so that for each of the sites its own template is loaded.
For example, there will be a file structure
__landing
____templates
______landing
________site_1
__________ index.html
________site_2
__________ index.html
It is necessary that when opening the first domain, templates from site_1 are loaded.
And when opening the second domain, templates from site_2 were loaded.
I think I need to write somehow template_loader, but I don’t understand yet how to do it.
Instead of nesting the "per-site" templates within the template directory structure, use two distincts root template directories, ie instead of
/templates
/app-one
site1/
index.html
site2/
index.html
you want:
/site1-templates
/app-one
index.html
/site2-templates
/app-one
index.html
Then in each setting file (you have a distinct settings for each site do you ?), just specify the proper path for TEMPLATES.DIRS
# site1 settings
TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(PROJECT_ROOT, 'site1-templates'),
],
'OPTIONS': {
# etc
}
}]
NB: if you need to keep some common templates, you can have them in a third directory (ie basetemplates) and add this after the site-specific path in TEMPLATES.DIRS.
TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(PROJECT_ROOT, 'site1-templates'),
os.path.join(PROJECT_ROOT, 'base-templates'),
],
'OPTIONS': {
# etc
}
}]

Trouble overriding the Django Admin template files

I have seen this question answered but I can't get it to work on my site. I have installed a site using Django 1.8 as I wanted to use the django-admin-bootstrapped plugin. I am also using the template provided by Heroku.
What I would like to do is override at the very least the base_site.html to change the site title and page title. However, I have tried several locations for this file including the following:
PROJECT ROOT
|--templates
|--admin
|--base_site.html
PROJECT ROOT
|--templates
|--admin
|--<appname>
|--base_site.html
PROJECT ROOT
|--<appname>
|--templates
|--admin
|--base_site.html
PROJECT ROOT
|--<appname>
|--templates
|--admin
|--<appname>
|--base_site.html
None of which work. I have the following in my settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'debug': DEBUG,
},
},
]
I am just wondering if I am doing something fundamentally wrong or if I just haven't found the magic location for the templates folder (or order of folders etc).
On a related note, is there anyway of debugging where the templates are being pulled from or is it just guesswork based on where they are supposed to be coming from?
Not every template in contrib/admin/templates/admin may be overridden per app or per model. The following can:
app_index.html
change_form.html
change_list.html
delete_confirmation.html
object_history.html
enter link description here
Override change_list.html to change the site title and page title

TemplateNotFound after installing django-messages and django-postman

I get a TemplateNotFound after I installed django-postman and django-messages. I obviously installed them separately - first django-postman, and then django-messages. This is so simple and yet I've spent hours trying to resolve this.
I'm using Django 1.8, a fresh base install using pip. I then installed the two above packages. The TEMPLATES portion of my settings.py file is as follows:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
#os.path.join(BASE_DIR, 'templates/django_messages'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Within my INSTALLED_APPS tuple, I've also installed the above packages as well.
Here's my addition to urls.py:
url(r'^messages/', include('django_messages.urls')),
No other changes were made to the system and yet when I go to /messages I get the following error message:
TemplateDoesNotExist at /messages/inbox/
django_messages/inbox.html
Request Method: GET
Request URL: http://localhost:8000/messages/inbox/
Django Version: 1.8.3
Exception Type: TemplateDoesNotExist
Exception Value:
django_messages/inbox.html
Exception Location: /projects/.virtualenvs/blatter/lib/python2.7/site-packages/django/template/loader.py in render_to_string, line 138
Python Executable: /projects/.virtualenvs/blatter/bin/python
Python Version: 2.7.6
The issue is because it extends from the site's base.html. It is also mentioned in postman documentation :- https://django-postman.readthedocs.org/en/latest/quickstart.html#templates
The postman/base.html template extends a base.html site template, in which some blocks are expected:
title: in <html><head><title>, at least for a part of the entire title string
extrahead: in <html><head>, to put some <script> and <link> elements
content: in <html><body>, to put the page contents
postman_menu: in <html><body>, to put a navigation menu
A possible solution can be found here :- django-postman extends a base.html that does not exist
The problem was resolved for django-messages after reviewing a called template and changing the extends/inheritance parameter.
The file that was being called, inbox.html, inherited "django_messages/base.html" ... which worked fine. "base.html" then inherited from "base.html," so there appeared to be some circular logic here causing the error. This is by default and wasn't added by me. When I removed the extends/inheritance declaration from "base.html" so that it didn't inherit from itself, django-messages worked.
Perhaps Django 1.8 changed some logic w/templates? Either way, issue resolved.