In our project, we have a bunch of different templates that clients to choose from (for their webstore). The file layout is something like this:
templates
cart.html
closed.html
head.html
standard
bishop
default
indiana
marley
mocca
nihilists
raconteurs
tripwire
Every subfolder of standard contains a few template files like base.html, browse.html and item.html. Browse and Item inherit from base.
What I want to do is render the browse template in a specific template folder (let's say templates/standard/bishop) isolated from any other global template path settings in my app. Is there a way to do that?
UPDATE: I'll try to be more clear. If I just render browse.html from the bishop subfolder it tries to extend base.html and it can't find it. I could alter the settings template path to include the bishop folder, but I'm looking for a way to make it work leaving that alone.
In your templates/standard/bishop/browse.html template you're doing the following:
{% extends "base.html" %}
This refers to templates/base.html and not templates/standard/bishop/base.html. By default Django will check your installed applications as well as the template directories that you specified under TEMPLATE_DIRS in settings.py.
This behavior is specified by TEMPLATE_LOADERS in settings.py:
http://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
You might be able to get away with what you're trying to do by creating your own template loader, otherwise simply specify the actual path to base.html:
{% extends "standard/bishop/base.html" %}
Related
I was moving a site over to wagtail and decided to use the codered extensions. The library comes with a image-gallery content-block. I want to use this but define a few templates you can choose from in the admin UI.
You usually define a template in the meta section, but I noticed a dropdown in the admin UI for a template.
How do I add a template to that dropdown? Link to the content block I want to change
I am interested in adding an HTML template and not inheriting from the content-block to change behaviour. (Unless inheriting is the only way to add a template to the dropdown.)
You could paramatise the path to the template you want to use then use an include in your block template to point to the chosen one.
For example, if you had a card block with selection for vertical or horizontal format. In your card block class you might have an property named template that uses a choice block, something like
class AlignmentChoiceBlock(ChoiceBlock):
choices=[
('blocks/flex/vertical_card.html', 'Vertical'),
('blocks/flex/horizontal_card.html', 'Horizontal')
]
Then in your block template, it just consists of:
<div class="some-block-container">
{% include value.template %}
</div>
Well, this works for Wagtail at least, not sure about codered.
The answer from Richard Allen works wagtail and is perfect for your own blocks etc. Wagtail blocks define a separate field that is used for their included components, for this you need another approach.
First you need to add the CRX_FRONTEND_TEMPLATE_BLOCKS to your django settings mysite/settings/base.py.
Then create a folder for your block templates in mysite/website/templates and create a custom template. Then add this path as a entry to the CRX_FRONTEND_TEMPLATE_BLOCKS. Entry key should be the block in lowercase. For a starter you could copy a template/html file from the codered package, found in coderedcms/blocks/
Now the template should be available from the template dropdown under the advanced menu of a crx block.
This info came from a gh issue of crx. This is e pretty recent addition and the dev mentioned that they are looking to make this easier. So this might change in the future, this worked for me on 26/01/2023.
I tried to add the path under INSTALLED_APPS and to create a folder of template tags and reuse them in multiple apps. But it is not working. Is there a smart way to work it out? All I need is to place templatetags for whole project in single directory accessible globally.
Template tags need to be in an app.
But once they are, they can be used by templates in any app. There is no need to do anything to make them available globally.
This worked for me. In your settings.py add:
AUTOLOAD_TEMPLATETAGS = (
'appname.folder.templatetags'
)
In the urls.py of your app, add:
from django.template.loader import add_to_builtins
from tag in settings.AUTOLOAD_TEMPLATETAGS:
add_to_builtins(tag)
Then in your template:
{% load templatetags %}
That should make them globally accessible.
We want one Django instance to serve different domains. The only difference between them is different templates, all the rest is the same. So we tried to just modify TEMPLATES.DIRS in a middleware. But Django templates loader ignores all the changes in TEMPLATES.DIRS made after settings.py is loaded.
Is there more or less standard Django Way to support different TEMPLATES.DIRS for different domains with just one settings.py?
To solve your problem use a template variable, both extend and include support variables. Just omit the quatation marks:
{% extends "base.html" %}
becomes
{% extends string_variable_with_file_name %}
Of cause you have to set that variable to the right filename in your context.
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