I am overriding a template file in django-suit. Unfortunately this file is not detected and overridden.
According to their documentation:
Alternatively you can copy base_site.html to any of template
directories, which are defined in TEMPLATE_DIRS setting (if any). By
default Django looks in every registered application templates/ dir.
I have copied the file base_site.html into an existing app/templates/admin directory but this is not detected. I am already consuming template files from this directory so it should work.
What may be wrong in my situation?
Make sure your app is above suit in INSTALLED_APPS in settings file.
This is really important step to learn how template loaders work. It checks the folders in order of app in INSTALLED_APPS setting if it finds the template in first folder it uses that template. That's why also suit has to be above admin app because it overrides admin templates.
Related
I have read several posts here where people discussed their preferred directory structure to keep various files of their Django project. But I get a file-does-not-exist error if I put my templates in the inner my_project folder instead of the outer my_project folder which contains the manage.py file. Is there some config file that specifies the default location of the templates (and other files)?can you please help me with the command change if I put templates in the inner (sub) folder? I just began my first Django project and would appreciate your help.
Ok, django looks for your templates at default places. I recommend you put your html files there (as a beginner).
Default places are:
- my_site_project/
-- templates/
--- base.html
--- navbar.html
--- footer.html
-- my_app1/
--- templates/
---- my_app1/
----- index_app1.html
----- about_app1.html
-- manage.py
If you put a general templates/ folder inside your project, same folder as your manage.py, those templates will be pulled.
If you want app specific templates the convention is to put a folder inside your app, again called templates/. This can lead to overlap if you put index.html inside your app-templates and an index.html inside your general templates/. Therefore you need to namespace the templates of your app. Create the app; create a folder called templates/ inside it; inside just created templates/folder you create another folder called my_app1; in that folder create your .html files.
Read the tutorial here. It is probably easier to understand than my jibberish. It is the official django tutorial.
A part of it:
First, create a directory called templates in your polls directory.
Django will look for templates in there.
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.
You can, in your settings.py via DIRS, specify where django looks for your templates. Although as a beginner I do not know why you should not stick to the conventions first.
For example I have 2 apps in my django project with templates and static files with identical subpath:
app1 /
static /
style.css
templates /
index.html
app2 /
static /
style.css
templates /
index.html
than, in settings.py I added this two apps:
INSTALLED_APPS = (
'app1',
'app2',
)
now I use in some way 'style.css' and 'index.html' in templates, e.g.
{% include 'index.html' %}
so, question is:
Does Django guarantee that when I reference to 'style.css' or 'index.html' will be used files from app2 subdirectories?
Is it any other way to point Django preferable variants of files in such situation?
As per documentation, first match wins:
Duplicate file names are by default resolved in a similar way to how
template resolution works: the file that is first found in one of the
specified locations will be used.
https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#django-admin-collectstatic
Now, when you tell Django to collect static files or render templates, Django asks special "finders" in order they are defined in your configuraiton for specified resource.
Default order for static files is "FileSystemFinder" that searches STATICFILES_DIRS in order they are added in it. If FileSystemFinder fails to find file in those dirs, Django uses next finder set, the "AppDirectoriesFinder" that searches in "static" subdirectories in your apps directories.
Same mechanic is applied to templates. When you tell Django to render "index.html", it first asks "filesystem.Loader" find template named like that in directories defined in TEMPLATE_DIRS. If search fails, Django asks next template loader, "app_directories.Loader" that searches template dirs in applications "templates" subdirs.
To answer your question, because app1 is registered before app2, Django will use it's style.css and index.html instead of ones coming from app2. If you want to change this behaviour, put app2 above app1 in your installed apps setting.
Documentation:
https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.loaders.app_directories.Loader
I'd like to extend django-registration with some custom forms and templates. What's the best practice for structuring your project to include these customizations? Would I just add my own 'registration' app and include the forms and templates there?
I know this is one of the strengths of Django, but I couldn't find any specific guidance on where to put this stuff.
You can easily customize the templates by creating a folder inside your templates directory named the same name as the app's template directory name you are overriding.
For example: if the app you want to override a template file in has the following structure:
django_registration/
templates/
django_registration/
login_form.html
(it is standard practice to create a sub template directory named the same as the app name) Then you just have to create a file with the same name, in a sub directory of your templates directory named django_registration:
my_app/
templates/
django_registration/
login_form.html
You can also just override any of the views and form classes that you need, and just import those classes instead of django-registration's classes
This is quite strange. As far as I knew, django always searches in local dir and then goes into Python installed lib dir. But this is not the case with django.contrib.comments.
I am trying to load list.html from local template director of the comments app. Its located exactly at templates/comments/list.html on local app dir.
The strange part is, it doesn't get loaded. It only loads the default one found in django.contrib.comments dir..
Why is it happening.
My app is correctly configured
Since something is going wrong I thought to check whether template dir is in path or not. So, I quickly loaded
{% include "comments/list.html" %} and it showed default file (not the custom one it supposed to show)
but I just changed list.html to list1.html and it was showing.
I changed the file name from list.html to list1.html and its working.
Make sure that your comments app appears above django.contrib.comments in your INSTALLED_APPS setting.
When you you using the app directories template loader, Django goes through your apps in the order they appear in you INSTALLED_APPS setting.
The template file is saved under the app directory, but it raises TemplateDoesNotExist exception while rendering:
Template-loader postmortem as following:
Django tried loading these templates, in this order:
Using loader django.template.loaders.app_directories.Loader:
...
$PROJECT/apps/myapp/templates/search.html (File does not exist)
...
I'm wondering why it looks for:
$PROJECT/apps/myapp/templates/search.html
rather than:
$PROJECT/apps/myapp/templates/myapp/search.html
The latter does exist indeed
$PROJECT/apps/myapp/templates/search.html. That is the path it'll look for as the doc says.
django.template.loaders.app_directories.Loader will look for a templates directory inside all the INSTALLED_APPS in order.
django.template.loaders.filesystem.load_template_source: This loader loads templates from the filesystem, according to TEMPLATE_DIRS. It is enabled by default.
django.template.loaders.app_directories.load_template_source: This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.
This means you can store templates with your individual applications, making it easy to distribute Django applications with default templates. For example, if INSTALLED_APPS contains ('myproject.polls', 'myproject.music'), then get_template('foo.html') will look for templates in this order:
/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Note that the loader performs an optimization when it is first imported: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.
This loader is enabled by default.
Supposing that you have a default project and app created as
django-admin startproject xyz
django-admin startapp abc
both xyz and abc folders are in main project folder
Following minimal changes are required to get first template working
in settings.py change INSTALLED_APPS to add 'abc' (I forgot and failed)
in urls.py add
add line: import abc.views
change urlpatterns to add path('abc/', abc.views.index)
in index definition of views.py use loader.get_template('abc/index.html')
Create abc/templates/abc/index.html file ( I wrote "template" and spent few hours before I realized that is was "templates")
make sure the templates and inside folders have execute permission and html file have read permission for "other" users. (I worked as root and failed due to this error)
Restart the project (runserver or apache2 service)
Summary of my mistakes
Edit INSTALLED_APPS
"templates" is default
setup x and r permissions
Ensure your app is added to settings.py INSTALLED_APPS
Ensure your config in apps.py has a name equal to the name of the application directory.
class DemoConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'app' # this must be the same as the parent directory
Add them to your settings file.
import os
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_DIRS = (
os.path.join(PROJECT_ROOT, "/apps/myapp/templates/"),
)