Tell django to search app's template subfolders - django

I have the following folder structure for the templates on my django app:
templates/
app/
model1/
model1_form.html
model2/
model2_form.html
Suppose I'm using model1 and a generic ListView, right now it only searches at templates/app/model1_form.html. Is there anyway I can tell django he should also search the app/ subfolders? I don't want to have to set the template name and path manually (template_name="templates/app/model1/model1_form.html").
At settings.py I have:
import os.path
BASE_PATH = os.path.dirname(os.path.dirname(__file__))
TEMPLATE_DIRS = (
BASE_PATH+'/templates/',
)
This is my view:
class HousesListView(ListView):
model = House
context_object_name = "house_list"
Thanks in advance!

The other answers were correct at the time, but for anyone coming across this now, this is how this is done in Django 1.8+
By default, Django now looks in app folders for templates. This is indicated by 'APP_DIRS': True, in the TEMPLATES setting like this:
TEMPLATES = [
{
...
'DIRS': ['templates'],
'APP_DIRS': True,
...
},
]
As the other answers indicate, you should still use appname/templates/appname/model1_form.html to namespace the templates
( more info: https://docs.djangoproject.com/en/1.8/intro/tutorial03/#write-views-that-actually-do-something in the box titled 'template namespacing')
Final check: make sure the app you're using is in the INSTALLED_APPS tuple, as that was the problem I was having.

You need to add django.template.loaders.app_directories.Loader to TEMPLATE_LOADERS (if it's not already).
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
Then, change your folder structure such that you have a "templates" folder in the app directory:
- <project_root>
- app
- templates
- model1
- model2
Or to properly namespace the models so they don't clash with other app names accidentally:
- <project_root>
- app
- templates
- app
- model1
- model2

I think to use templates from subfolders generally you either have to:
Manually give the template path as subdir/template.html
eg. render_to_response('sub/dir/template.html') or template_name='...'
Define all the subfolders in the TEMPLATE_DIRS
eg.
TEMPLATE_DIRS = (
BASE_PATH+'/templates/',
BASE_PATH+'/templates/app',
BASE_PATH+'/templates/app/model1',
)
But because Generic Views except templates to be found in app_name/template.html,
you would have to move your templates to add /path/to/templates/app/model1 to your TEMPLATE_DIRS, and move your templates to templates/your_app/model/your_app/model_template.html, which is little bit awkward.

With Django 2.0, it's not even necessary to change anything in the TEMPLATES variable in settings.py.
The only requirement is to add appname.apps.AppnameConfig (e.g. catalog.apps.CatalogConfig for an app named 'catalog') to the INSTALLED_APPS list, then django will look under appname/templates when it searches for templates.

Related

Django Templates: How does it decide where to load a template?

I was following the Django Girls Tutorial up to the point where we add the login capabilities and I've gotten to a point where it tries to load from a different template folder than I want.
I have all my blog templates in blog\templates\blog\, etc. and that is where Django is looking for my login.html. However, in the tutorial (and as a result in my folder structures), the path for login.html is: mysite/templates/registration/login.html. So how would I make Django look there?
Sorry if this is a stupid question.
Django will look to your settings.py for how to load templates, and the order in which it should try to load templates. It's likely that you haven't configured django to look for templates in mysite/templates.
There's a setting called TEMPLATE_DIRS which is a list of absolute paths for your template folders. So in your settings.py file, try something like below. Read my comments to see what each line does.
# create a variable that stores the absolute path to your project's root directory
# you might have something like this already defined at the top of your settings.py
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
# this is the default value for TEMPLATE_LOADERS
# which says to look at the `TEMPLATE_DIRS` variable, and then in each of your app's subdirectories for templates
TEMPLATE_LOADERS = ('django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader')
# the special sauce. tell django to look at the "templates" folder
TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'templates'), )

Adding new template folder in Django

Say I have the following folder structure
mysite
- mysite
- templates
- books
- templates
- contact
- templates
And I have the following in my settings.py
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)
How would I configure the site to look in the templates folder of any sub directory? For example, say I wanted to add another folder to my existing 3 (mysite, books, contact) called "test". I would want the site to automatically know to search in "test/templates".
I am wondering if it is as simple as:
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
os.path.join(os.path.dirname(__file__), 'mysite/templates').replace('\\','/'),
os.path.join(os.path.dirname(__file__), 'books/templates').replace('\\','/'),
os.path.join(os.path.dirname(__file__), 'contact/templates').replace('\\','/'),
)
To me, that looks like it would point to "/mysite/books/templates" not "/books/templates"
I use something like this:
TEMPLATE_DIRS = (
join(BASE_DIR, 'templates'),
)
And then i put all my templates under the templates folder (which is under the same directory as manage.py). This way i can find all the templates for my project in the same place.
+templates
-app1 templates
-app2 templates
When i need to access a template i just use 'app1/my_template.html'.

Use custom directory for "templatetags"

some one know if its likely use custom directory for "templatetags" eje: "my-project/templatetags"
Normal
My-Project-Name
My-App
__init__.py
templatetags
__init__.py
Need Some Like This
My-Project-Name
templatetags
__init__.py
This is possible. Just add location of your templatetags.py or templatetags directory to Django settings.py into OPTIONS in TEMPLATES setting.
In my case I put my templatetags in the libs/ directory that is located in project root dir.
You have two options, builtins or libraries:
TEMPLATES = [{
...
'OPTIONS': {
...
'builtins': [
'libs.templatetags'
],
# or as #x-yuri pointed out, you can put them in `libraries`
'libraries': {
'my_tags': 'libs.templatetags',
},
}
}]
If you use builtins, it is available everywhere and you don't need to use {% load %} for that.
If you use libraries you need to use {% load my_tags %}.
This is not possible. The reason being, templatetags must reside inside a django app.
From the documentation of templatetags:
Custom template tags and filters must live inside a Django app. If
they relate to an existing app it makes sense to bundle them there;
otherwise, you should create a new app to hold them.
The app should contain a templatetags directory, at the same level as
models.py, views.py, etc. If this doesn’t already exist, create it -
don’t forget the __init__.py file to ensure the directory is treated
as a Python package. After adding this module, you will need to
restart your server before you can use the tags or filters in
templates.

Templates in shared apps

I have two django projects that share some common apps,
this is my structure:
prj_1
prj_2
common_apps
From prj_1 and prj_2 I use the common apps and I'd like to render these apps with different templates.
How can I do?
Yes, using the following directory structure:
common_apps
app1
templates
app1
# default templates for common app live here
prj_1
templates
app1
# overridden templates for app1 live here (using same file name)
This isn't clearly spelled out in the docs in one place, but your prj_1 templates will override common_apps because the default setting in Django looks like:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
...and your typical Django settings file will have something like this:
TEMPLATE_DIRS = (
os.path.join(PROJECT_ROOT, 'templates'),
# where PROJECT_ROOT is absolute path to prj_1/
)
...which means when looking for say 'app1/base.html' the filesystem.Loader will get called first and will find any overridden templates in prj_1 so app_directories.Loader won't get called.
Some info here:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overriding-admin-templates

Django-Oscar override templatetags

I tried to override category_tags by creating a local version of catalogue application with a local templatetags folder which has a category_tags.py file (also init.py).
It seems the default category_tags file is used.
If I change the name of my local tag file and of course I load the new name of the tag in the template it works but I would like to override or extend the default category_tags not to create another one.
Any ideas?
thanks!
I got it working by putting the templates in my project_folder > templates > oscar_app_name > template_name.html
So to override the "checkout" app and template, my structure looks like this:
/project
--/apps
----/checkout
------[change checkout models]
----__init__.py
----app.py
--/project
----/templates
------/checkout
--------payment_details.html
----__init__.py
----settings.py
----urls.py
--manage.py
And then you have to edit settings.py Installed Apps
INSTALLED_APPS = [
'django.contrib.admin',
...
'compressor',
'paypal',
] + get_core_apps(['apps.checkout'])
I would assume that template tags get loaded in the order specified in INSTALLED_APPS. Does the app containing your category_tags.py come before (or instead of, e.g. when using Oscar's get_core_apps override to extend an Oscar core app) oscar.core.apps.catalogue?
PS. I'm an Oscar author and have to admit we don't check StackOverflow very often. The mailing list is your best bet at the moment.