Pointing Django to Different Template Directory - python

I am currently building a Django ecommerce site that is based on Django-Oscar. By default the latter comes with a basic Bootstrap theme and styles.
I moved these template files into
project_root/templates/oscar
It is my understanding that if I were to override these templates, it would override the original Oscar templates located in the virtualenv.
The next step is that I downloaded a different theme that I would like to use for the site.
In particular, I would like that theme to reside in
project_root/templates/main_theme
The trouble is that I cannot seem to get Django to pickup the templates from that directory. If I delete project_root/templates/oscar, it appears to resort back to the default Oscar templates.
If I place a base.html into project_root/templates/ and make that base.html to be the main file of the new theme, it is displayed. However, I would still like to break it up into smaller files and have them "live" in a separate directory. How can I accomplish this? Is there a more prudent way of going about this?
Here are some relevant settings:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.flatpages',
'django.contrib.sites',
'compressor',
'widget_tweaks',
] + get_core_apps()
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
OSCAR_MAIN_TEMPLATE_DIR,
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.i18n',
'django.contrib.messages.context_processors.messages',
'oscar.apps.search.context_processors.search_form',
'oscar.apps.promotions.context_processors.promotions',
'oscar.apps.checkout.context_processors.checkout',
'oscar.apps.customer.notifications.context_processors.notifications',
'oscar.core.context_processors.metadata',
],
},
},
]
COMPRESS_ROOT = os.path.join(BASE_DIR, "static")
STATIC_URL = '/static/'
#STATIC_ROOT = os.path.join(BASE_DIR, "static")
#This should be commented out in Development
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

The following code worked for me. As it turned out, one needed to specify an additional entry in the DIR list of the TEMPLATES list.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
#re-route the search for templates into this custom template directory
os.path.join(os.path.join(BASE_DIR, 'templates'), 'tshirt-theme'),
#Uncomment the line below to restore the original Oscar template
#OSCAR_MAIN_TEMPLATE_DIR,
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.i18n',
'django.contrib.messages.context_processors.messages',
'oscar.apps.search.context_processors.search_form',
'oscar.apps.promotions.context_processors.promotions',
'oscar.apps.checkout.context_processors.checkout',
'oscar.apps.customer.notifications.context_processors.notifications',
'oscar.core.context_processors.metadata',
],
},
},
]

You could also assign the different path to directories as variables :
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates/local')
OSCAR_TEMP_DIR = os.path.join(BASE_DIR, 'templates/oscar')
TEMP_DIR = os.path.join(BASE_DIR, 'templates')
And in the Templates section of settings.py, assign these variables to Directory arg.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATES_DIR, OSCAR_TEMP_DIR, TEMP_DIR],
'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',
'oscar.apps.search.context_processors.search_form',
'oscar.apps.checkout.context_processors.checkout',
'oscar.apps.customer.notifications.context_processors.notifications',
'oscar.core.context_processors.metadata',
],
},
},
]
Now, you can put and use your templates from either
project_dir/templates/local OR
project_dir/templates/oscarOR
project_dir/templates/ For Any template file that intersects
both(eg: main base.html).
Just easier to read and cleaner code if you have to use multiple template directories.

Related

Forking Django Oscar's static files doesn't work

I'm trying to fork default oscar's static. My folder structure is the following:
myproject/
static/
oscar/
templates/
flatpages/
oscar/
myproject/
And I set the following settings:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / 'static/'
]
Forking templates works just fine, but the same thing doesn't work with static, default files are still served in HTML. To fork static I used this command:
./manage.py oscar_fork_static
Any idea why is it so?
Add this inside templates in settings.py file
'libraries' : {
'staticfiles': 'django.templatetags.static',
EX:
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',
],
'libraries' : {
'staticfiles': 'django.templatetags.static',
}
},
},
]
}
See if this is helps you

In password reset view custom templates not loading?

I am working on rest password via custum templates in django,but custom template not loading it is loading django's default template every time i load the /password_reset/ url.
I am using the url
url('^', include('django.contrib.auth.urls')),
i have a registration folder in templates and using this link to work
https://simpleisbetterthancomplex.com/tutorial/2016/09/19/how-to-create-password-reset-view.html
and the template folder is:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
],
'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',
"cms.utils.context_processors.permission_based_hidding_of_sidebar",
],
'libraries':{
'template_tag': 'cms.templatetags.template_tag',
'template_tag_time': 'cms.templatetags.tags',
}
},
},
]
install apps in settings:-
INSTALLED_APPS = [
'cms',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'django_csv_exports',
'django.contrib.auth',
'django.contrib.admin',
]
See my comment below. Sure, you can hack it and remove the form in the distribution library. Very very naughty. A much better solution is to alter the order in which the apps are loaded in your settings file. Originally I had:
INSTALLED_APPS = ['django.contrib.auth', 'ana_access',]
I just changed this so my app loaded first. And lo. That did it.
INSTALLED_APPS = ['ana_access','django.contrib.auth', ]
Conclusion: if you keep seeing the default page DESPITE having the form in your templates/registration folder, then it might be because you are loading the default django.contrib.auth app before your own.
Django 3.0. 2020. I solved the issue by adding template/registration/*.html in the project directory. This solved my issue. I don't need to change anything in the INSTALLED_APPS list.
Here are the steps:
Do the following highlighted changes in "settings.py"
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # **ADD THIS
'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',
'django.template.context_processors.media',
'django.template.context_processors.static', # * (optional)
],
},
},
]
Create templates/registration directories in your project root folder and add your registration templates here instead of your_app/templates/registration.
Project_root_folder/templetes/registration/*.html
No need to change anything in INSTALLED_APPS of settings.py
If you want to override the Django admin template you need to created admin folder inside your templates directory. And place all your admin's files and folders there...
templates
|__ admin
|__ registration
Update: Also please correct the TEMPLATES DIR It should be
'DIRS': [os.path.join(BASE_DIR, 'templates')],

Add templates folder in Django 1.8

I have some problem adding the templates directory for my django project. My goal is to override the /django/contrib/admin/templates/registration/password_reset_form.html file.
My Django version is the 1.8. This is the templates part of my settings.py:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_PATH = os.path.join(BASE_DIR, 'templates')
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [PROJECT_PATH],
'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',
],
},
},
]
In the templates folder inside my django project i add the modified password_reset_form.html.
My urls.py is like this:
url(r'^password/reset/$',auth_views.password_reset,name='password_reset'),
url(r'^password/reset/done/$',auth_views.password_reset_done,name='password_reset_done'),
url(r'^password/reset/complete/$',auth_views.password_reset_complete,name='password_reset_complete'),
url(r'^password/reset/confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',auth_views.password_reset_confirm,name='password_reset_confirm'),
I always do:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_PATH = os.path.join(BASE_DIR, 'templates')
print "Templates in: %s" %(PROJECT_PATH)
To make sure I have them in the right spot. What does that print? Also, post the output from find /path/to/templates where the path is the output from that print statement.
just copy the admin/templates/registration/password_reset_form.html to your templates folder and override it there. you dont need any change in settings

Templates problems in django

I wrote an app in django. And I want to write a index.html for it. But I can't make it run. I tried and inspect the settings and code but, it doesn't work either. I will paste the code. Hope someone can find the trick.
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',
'django.core.context_processors.static',
],
},
},
]
I wrote a app named blog. I put the index.html in the ,blog/templates/blog/
views.py
def index(request):
posts = Post.objects.filter(published=True)
return render(request,'blog/index.html',{'posts':posts})
urls.py:
urlpatterns = [
url(r'^$', views.index, name='index')
]
I can't find any problems but it just does not work. It seems the template is not found but the config path is right. Or I missed something that I unaware of?
Add 'blog' to the INSTALLED_APPS tuple in settings.py
Also, below are the settings that work for me. Hope these will do the trick for you as well.
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_BASE_PATH = os.path.dirname(__file__)
PROJECT_DIR_NAME = os.path.split(PROJECT_BASE_PATH)[1]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(PROJECT_BASE_PATH, 'templates').replace('\\', '/')],
'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',
],
},
},
]
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)

What is the path that Django uses for locating and loading templates?

I'm following this tutorial on a Windows 7 environment.
My settings file has this definition:
TEMPLATE_DIRS = (
'C:/django-project/myapp/mytemplates/admin'
)
I got the base_template from the template admin/base_site.html from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into an admin subdirectory of myapp directory as the tutorial instructed, but it doesn't seem to take affect for some reason.
Any clue of what might be the problem?
I know this isn't in the Django tutorial, and shame on them, but it's better to set up relative paths for your path variables. You can set it up like so:
import os.path
PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))
...
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media/')
TEMPLATE_DIRS = [
os.path.join(PROJECT_PATH, 'templates/'),
]
This way you can move your Django project and your path roots will update automatically. This is useful when you're setting up your production server.
Second, there's something suspect to your TEMPLATE_DIRS path. It should point to the root of your template directory. Also, it should also end in a trailing /.
I'm just going to guess here that the .../admin/ directory is not your template root. If you still want to write absolute paths you should take out the reference to the admin template directory.
TEMPLATE_DIRS = [
'C:/django-project/myapp/mytemplates/',
]
With that being said, the template loaders by default should be set up to recursively traverse into your app directories to locate template files.
TEMPLATE_LOADERS = [
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
# 'django.template.loaders.eggs.load_template_source',
]
You shouldn't need to copy over the admin templates unless if you specifically want to overwrite something.
You will have to run a syncdb if you haven't run it yet. You'll also need to statically server your media files if you're hosting django through runserver.
If using Django settings as installed, then why not just use its baked-in, predefined BASE_DIR and TEMPLATES? In the pip installed Django(v1.8), I get:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
### ADD YOUR DIRECTORY HERE LIKE SO:
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',
],
},
},
]
Smart solution in Django 2.0.3 for keeping templates in project directory (/root/templates/app_name):
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMP_DIR = os.path.join(BASE_DIR, 'templates')
...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMP_DIR],
...
in views.py just add such template path:
app_name/html_name
For Django 1.6.6:
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
TEMPLATE_DIRS = os.path.join(BASE_DIR, 'templates')
Also static and media for debug and production mode:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
if DEBUG:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
else:
STATIC_ROOT = %REAL_PATH_TO_PRODUCTION_STATIC_FOLDER%
MEDIA_ROOT = %REAL_PATH_TO_PRODUCTION_MEDIA_FOLDER%
Into urls.py you must add:
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf.urls.static import static
from django.conf import settings
from news.views import Index
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
...
)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
In Django 1.8 you can set template paths, backend and other parameters for templates in one dictionary (settings.py):
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
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',
],
},
},
]
Official docs.
I also had issues with this part of the tutorial (used tutorial for version 1.7).
My mistake was that I only edited the 'Django administration' string, and did not pay enough attention to the manual.
This is the line from django/contrib/admin/templates/admin/base_site.html:
<h1 id="site-name">{{ site_header|default:_('Django administration') }}</h1>
But after some time and frustration it became clear that there was the 'site_header or default:_' statement, which should be removed. So after removing the statement (like the example in the manual everything worked like expected).
Example manual:
<h1 id="site-name">Polls Administration</h1>
Alright šŸ˜ Let's say you have a brand new project, if so you would go to settings.py file and search for TEMPLATES once you found it you just paste this line os.path.join(BASE_DIR, 'template') in 'DIRS' At the end, you should get somethings like this :
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'template')
],
'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',
],
},
},
]
If you want to know where your BASE_DIR directory is located type these 3 simple commands:
python3 manage.py shell
Once you're in the shell :
>>> from django.conf import settings
>>> settings.BASE_DIR
PS: If you named your template folder with another name, you would change it here too.
In django 3.1, go to setting of your project and import os
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',
],
},
},
]
Contrary to some answers posted in this thread, adding 'DIRS': ['templates'] has no effect - it's redundant - since templates is the default path where Django looks for templates.
If you are attempting to reference an app's template, ensure that your app is in the list of INSTALLED_APPS in the main project settings.py.
INSTALLED_APPS': [
# ...
'my_app',
]
Quoting Django's Templates documentation:
class DjangoTemplatesĀ¶
Set BACKEND to 'django.template.backends.django.DjangoTemplates' to configure a Django template engine.
When APP_DIRS is True, DjangoTemplates engines look for templates
in the templates subdirectory of installed applications. This generic name was kept for backwards-compatibility.
When you create an application for your project, there's no templates directory inside the application directory. Django admin doesn't create the directory for you by default.
Below's another paragraph from Django Tutorial documentation, which is even clearer:
Your projectā€™s TEMPLATES setting describes how Django will load and render templates. The default settings file configures a DjangoTemplates backend whose APP_DIRS option is set to True. By convention DjangoTemplates looks for a ā€œtemplatesā€ subdirectory in each of the INSTALLED_APPS.
In django 2.2 this is explained here
https://docs.djangoproject.com/en/2.2/howto/overriding-templates/
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
INSTALLED_APPS = [
...,
'blog',
...,
]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
...
},
]
basically BASE_DIR is your django project directory, same dir where manage.py is.
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',
],
},
},
]
By default django looks for the template folder in apps. But if you want to use template folder from root of project, please create a template folder on root of project and do the followings in settings.py:
import os
TEMPLATE_DIR = os.path.join(BASE_DIR, "templates")
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_DIR],
'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 can easily add template folder in settings.py folder, os.path is deprecated in django 3.1, so you can use path instead of os.path. You just have to import path in settings.py, you have to specify the base directory, then you have to specify template path, and last but not the least, you have to add template folder path in TEMPLATES = [{}], for example:
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATE_DIR = Path(BASE_DIR, 'templates') (you can name TEMPLATE_DIR to any name)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_DIR],
'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',
],
},
},
]
One interesting thing I noted for templates searching
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
#'DIRS': [os.path.join(BASE_DIR,"templates")],
'DIRS': [],
'APP_DIRS': True,
if the app folder have templates sub-folder then only it is searched and listed under Template-loader postmortem
If app/templates do not exist, it is not listed in error messages. Understanding this will prevent newbee to add template folders via DIRS directive
This is for DJANGO version 4.x.x
To add templates folder open file settings.py and modify
'DIRS': [BASE_DIR / 'templates'],
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [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',
],
},
},
]

Categories

Resources