Let's say I have this structure:
{# base.html #}
{% block content %}{% endblock %}
{# page.html #}
{% extends "base.html" %}
{% block content %}
{% include "snippet.html" %}
{# and I also want somehow to redefine {% block snippet_content %} of snippet here #}
{% endblock %}
{# snippet.html #}
<bells_and_whistles>
{% block snippet_content %}{% endblock %}
</bells_and_whistles>
I hope that the code is self-explaining.
Is there an elegant way to achieve this?
I'm afraid it is not possible in the way you want to do it.
Your options are:
Create a modified_snippet.html inheriting from snippet.html and overriding the block and include it instead
Change your snippet_content block to a {{ snippet_content }} variable and pass its contents using {% include "snippet.html" with snippet_content="My content" %}. Of course this method is quite limited.
Related
I am developing a dictionary application using Django. One of the main themes of the app is displaying feeds of definitions.
Specifically, I have:
an "index" feed where new definitions are listed,
a "headword" feed where definitions of a particular headword are listed,
and a "tag" feed where definitions tagged with a particular tag are listed.
index.html:
{% block body %}
<h1>Definitions</h1>
<ul>
{% for definition in definitions %}
// definition HTML
{% endfor %}
</ul>
{% endblock %}
headword.html:
{% block body %}
<h1>{{ headword }}</h1>
<ul>
{% for definition in headword.definitions_headword.all %}
// definition HTML
{% endfor %}
</ul>
tag.html:
{% block body %}
<h1>{{ tag }}</h1>
<ul>
{% for definition in tag.definitions_tag.all %}
// definition HTML
{% endfor %}
</ul>
Clearly, I need a base feed.html template that these three files can share. For the h1 tag no problem. However, I am having problems with the for loop iterable variables.
I tried nesting a {% block iterable %}{% endblock %} in the for loop of feed.html as in {% for definition in {% block iterable %}{% endblock %} %} and then plugging definitions, headword.definitions_headword.all, and tag.definitions_tag.all in {% block iterable %}, but Django does not seem to support that.
I could probably pass to all three templates a "definitions" context variable and use that as the iterable in all three for loops, but is there a way to do it without touching Python code?
Your explanation was a bit fuzzy to me at the end there, but going just based off your first sentence of "Clearly, I need a base feed.html template that these three files can share."
I think {% include %} may be what you are looking for.
https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#include
Create your base template of "feed.html" which includes generic variables. Generic variables below are "header_name" and "definitions".
<h1>{{ header_name }}</h1>
<ul>
{% for definition in definitions %}
// definition HTML
{% endfor %}
</ul>
In your parent templates (index, headword, tag), use the "include" tag. Pass in your parent template variables into the child template. Examples below:
headword.html
{% block body %}
{% include 'pathname/feed.html' with header_name=headword definitions=headword.definitions_headword.all %}
{% endblock %}
tag.html
{% block body %}
{% include 'pathname/feed.html' with header_name=tag definitions=tag.definitions_tag.all %}
{% endblock %}
If I have this in my "main" (or project's) base.html:
{% block content %}
I'm inside block content.
{% block main_sidebar %}
I'm inside my sidebar now.
{% endblock main_sidebar %}
{% endblock %}
And, in the app's base.html (this base extends off the main base.html), I have this:
{% block main_sidebar %}
I want to change this.
{% endblock main_sidebar %}
The output doesn't change in my app's base.html for the main sidebar.
If I change {% block content %} to a custom name, then it works. I guess {% block content %} has special privileges as a block name and so can't be overwritten in a case like the one above?
I need to create a small side block with form(it contains only one field and button) and I want it to be included to every page except base.html
I thought about making simple view function, but maybe there are better ways to do this?
I'm using Python and Django 1.6
In general, you shouldn't use base.html directly, but because you are and because it would be a huge hassle to change it in every other template, what you can do is, in the view function that returns base.html, you can add a boolean to the context and check the boolean to determine what template you are using.
Something like this:
def view_that_uses_base.html(request):
is_base = True
return render_to_response("base.html", {"is_base":is_base}, RequestContext(request,{}))
And then in the template:
{% block sidebar %}
{% if is_base%}
{% else %}
#Your code here
{% endif %}
{% endblock sidebar %}
You must use templates to do that.
In other words, try creating $DJANGO_ROOT/templates/main.html using the following code:
<html>
<head>
</head>
<body>
{% block one_field_and_a_button %}
<input />
<button>I am everywhere</button>
{% endblock %}
{% block my_custom_content %}
{% endblock %}
</body>
<html>
Then all other templates must extend that main.html template and insert their own data.
Imagine this is $DJANGO_ROOT/templates/login.html. It will only replace "my_custom_content" and will inherit all other blocks including "one_field_and_a_button"
{% extends 'templates/main.html' %}
{% block my_custom_content %}
Hello World! This is the login
{% endblock %}
Finally, if you want to have a base.html that does not have that part of the code containing one field and a button, you can do the following.
Imagine this is $DJANGO_ROOT/templates/base.html. It will replace both "one_field_and_a_button" and "my_custom_content". However, in this case, "one_field_and_a_button" will be replaced with blank space that will not show in your html code.
{% extends 'templates/main.html' %}
{% block one_field_and_a_button %} {% endblock %}
{% block my_custom_content %}
Hello World! This is my base.html template
{% endblock %}
Hope it works for you!
You can use block tag in base.html, i think you are searching foe something like this
base.html
{% block code %}
{% include 'sidebar.html' %}
{% endblock %}
index.html
{% extends base.html %}
{% block code %}
{% endblock %}
and every other templates
just extend base html
{% extends base.html %}
I tried to make a state_template.html with
{% load inplace_edit %}
{% block extra_header %}
{% inplace_static %}
{% endblock %}
{% inplace_edit "action.action_state" %}
And tables.py has:
action_state = tables.TemplateColumn(template_name='django_tables2/state_template.html', verbose_name="State")
But since action is never being passed to the template, it is giving an error.
Does anyone have any ideas on how to make this work?
This is a very nice question :-)
I think if you update your template (state_template.html), with this should works:
{% load inplace_edit %}
{% block extra_header %}
{% inplace_static %}
{% endblock %}
{% inplace_edit "record.action_state" %}
And this is a recomendation, You should move to the template of the view that renderthe table, but this is only to efficiency:
{% block extra_header %}
{% inplace_static %}
{% endblock %}
I'm looking to set a default behavior in a template to be included.
I have a problem with Django template system not allowing to set variables in template (I've read about the Django Philosophy, and I understand it).
Here is my example problem:
I want to include a template to render a newsfeed:
template.html:
...
{% include "_newsfeed.html" with slicing=":20" %}
...
I would like to not be forced to enter the slicing argument, and set a default behavior, let's say ":20"
In my _newsfeed.html , I would like to do (pseudo-code, it doesn't work):
_newsfeed.html:
...
{% if not slicing %}{% with slicing=":20" %}{% endif %}
{% for content in newsfeed_content|slice:slicing %}
{# Display content #}
{% endfor %}
{% if not slicing %}{% endwith %}{% endif %}
Instead, I end up doing this below, that doesn't follow the DRY rule (and doesn't satisfy me!):
_newsfeed.html:
...
{% if not slicing %}{% with slicing=":20" %}
{% for content in newsfeed_content|slice:slicing %}
{# Display content #}
{% endfor %}
{% endwith %}{% else %}
{% for content in newsfeed_content|slice:slicing %}
{# Display content #}
{% endfor %}
{% endif %}
How should I do ?
If you want to do this via your template not your views file, you could create your own filter based on slice e.g.
from django.template.defaultfilters import slice_filter
#register.filter("slice_default", is_safe=True)
def slice_filter_20(value, arg=":20"):
return slice_filter(value, arg)