It took me forever to find out why a template was not getting overridden, only to find that it seems Django simply does not use the correct precedence in overriding the templates.
The templates I'm trying to change are the ones for changing the user's password, which are loaded for the URL /accounts/password/change.
I have my modified templates in mysite/myapp/templates/registration; the system default templates are at /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/admin/templates/registration. When templates are present in both these directories, Django uses the system (/Library) ones. Huh?
When I remove the templates in /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/admin/templates/registration
, the correct ones (i.e. mine, in mysite/myapp/templates/registration) are loaded.
How to fix this issue? That is, how to make Django load my overridden templates without having the delete the original templates found in the /Library?
you have to create an admin directory inside the templates dir in which you set the templates you want to override
In order to override one or more of them, first create an admin directory in your project’s templates directory. This can be any of the directories you specified in TEMPLATE_DIRS.
Read the Django doc here
Related
I am new to Django and I have a path to my HTML file as
./templates/registration/login.html and I want to change it to
./templates/index/login.html
After renaming it to /templates/index/login.html, it is still picking up the old directory /templates/registration, could not find login.html screen and it throws an error.
Could someone tell me what changes we have to make in settings.py when we rename a folder name inside templates structure?
In your settings.py, you can define the templates location, which applies the template function per app.
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates')
)
I assume your app is named registration, hence why it is looking there. You can either rename your app or place all your templates in a global folder at the same level as the apps (and not within the apps themselves). The latter is not recommended for large applications.
Edit: Why is this labeled Python2? What version of Django is this?
Django tutorial suggests to organize templates like this:
Within the templates directory you have just created, create another directory called polls, and within that create a file called index.html. In other words, your template should be at polls/templates/polls/index.html. Because of how the app_directories template loader works as described above, you can refer to this template within Django simply as polls/index.html.
Tutorial also tells what happens if I just put index.html in polls/templates:
Now we might be able to get away with putting our templates directly in polls/templates (rather than creating another polls subdirectory), but it would actually be a bad idea. Django will choose the first template it finds whose name matches, and if you had a template with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those templates inside another directory named for the application itself.
My assumption was that as long as I'm creating an isolated application, it's templates are also isolated from other apps without any subfolder magic.
Is there another way to namespace, so I can refer to template as index.html without creating duplicated folders?
The way templates are organised in a Django project is very flexible. So there's nothing to stop you ordering the template files however you want, as long as you specify the correct template name in the view. For example, you could use a Class Based View for the list of Polls, specifying the template_name as whatever you like:
# polls/views.py
from django.views.generic import ListView
from .models import Poll
class PollList(ListView):
model = Poll
template_name = 'any/path/you/choose/any_name.html'
Having said that, it's good to create a consistent template structure to keep the code maintainable. I'd recommend at the very least keeping your page-level templates (things which are used to return the whole html page) structured in folders with their relevant app name, and anything you include (snippets included with the {% include %} tag) within includes subfolders, like so:
templates
- base.html
polls
- poll_list.html
includes
- poll_votes.html
Edit:
If you still need namespaces despite this, you could use URL namespaces.
I am reading through the Django tutorial How to write reusable apps. I am trying to figure out how to package HTML base templates so that people who install my app (through pip) can extend them (e.g. with {% extends %}.) When I import a python module I don't have to know its location on the filesystem, but is that the case for Django templates?
(Side note: My project consists of plumbing that make it easier to write a specific type of app. So I have various abstract base classes [models, views, forms], template tags, URL configuration, and HTML templates that users can inherit from. It also contains customizations to Django Admin. Right now it is a project but I am trying to package it as an app because according to what I am reading, that seems to be the right way to package Django code, but maybe I should be doing it differently.)
Use a template dir structure like this:
awesome_app_name/
templates/
awesome_app_name/
base.html
cool_template.html
This allows someone to extend your templates with:
{% extends 'awesome_app_name/cool_template.html' %}
OR they could just swap it out with their own template like this:
my_app_name/
templates/
my_app_name/
my_template.html
awesome_app_name/
cool_template.html <-- this overloads your template with their own
This makes for very flexible templates in shared packages.
EDIT:
This works if you configure django with both a template directory for your project and the app_directories.Loader template loader. I believe this to be the configuration used by most:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(PROJECT_DIR, 'templates'),
)
Template loading is then done in the following order:
Resolve template from project directory
Resolve template from app directories
Here's an example project that follows this structure: https://github.com/brutasse/django-password-reset
I got a bit confused, because when I use the generic ListView class, Django is looking for "appname/objectname_list.html" inside the "appname/templates" folder. This results in:
appname/templates/appname/objectname_list.html
If I supply "template_name", it does not require the subfolder inside the templates folder anymore.
Why doesn't it find the objectname_list.html inside the "templates" folder like before in 1.3 ? Did I configure something wrong or did they change the place where I'm supposed to put my templates as well ? In 1.3 I used to place template html files inside "appname/templates" directly instead of using a subfolder.
For me it does not make sense to use another subfolder with the name of the app, where the templates folder is already in. Or am I missing something useful ?
I could not find anything about it in the release notes.
I don't think this is 1.4 specific. If you will want your template in a subfolder, specify template_name = 'subfolde/template.html'
Regarding template dirs, from the docs:
... For each app in
INSTALLED_APPS, the loader looks for a templates subdirectory. If the
directory exists, Django looks for templates in there.
So the actual dir is:
projectname/appname/templates/appname/objectname_list.html
^^^ ^^^
This helps you keep everything inside the app folder and does not require you to configure anything,
This also means that if you have apps foo, bar and baz, you can still have one templates dir under one of the apps:
myproj/foo/templates/foo/...
myproj/foo/templates/bar/...
myproj/foo/templates/baz/...
I have my template folder with all html templates lieing together in the template folder with no directory structure as such.
I decided to arrange them on per app basis, but:
A template with template-tags belong to different apps.
Eg:
Login page(Login app) includes a banner that belongs to UserActivity [User activity app]. So, if I include the login template in login folder in templates, then it will be including stuff across other app's template folder.
How should I structure so that all that referred stays in 1 place organized ?
Feel free to ask for more info.. :)
Organizing your templates in subdirectories is definitely they way to go, but I am not sure if you can really reach the level of separation you are looking for.
If your apps depend on each other you'll always have includes and tags from other apps. So i'd put the templates to the app they belong to.
But maybe the docs about template loaders can help you clarify your structure.
For example the app_directories.Loader
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.
So you could put app-specific templates in in your app directories and keep your general templates (base.html, etc.) in the top level template dir of your project.