Why does template inheritance in Django not show error? - django

I'm not seeing an error when template inheritance seems to fail. I don't see content from the child template but I don't see a 'TemplateNotFound' error. If I change the path to the parent template to 'notthefilename.html' I still don't see an error. Is there a way to make template inheritance fail noisily? I have no idea why this is not working even though I have a similar inheritance in a adjacent folder that is working as expected.
generic_create.html The text 'hello2' is rendering.
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div style= "padding-top: 30px">
<form method="post">{% csrf_token %}
{% if model_name == 'TransactionsTable' %}
<div>
{% block transactions_create %}
hello2
{% endblock transactions_create %}
</div>
{% else %}
{{ form |crispy }}
{% endif %}
<div id="container">
<input type="submit" class="btn btn-default" value="Save">
Cancel
<div>
</form>
</div>
{% endblock content %}
transactions_create.html - The content 'Hello1' is not rendering
{% extends "generic_create.html" %}
{% load static %}
{% block transactions_create %}
Hello1
{% endblock transactions_create %}

Thanks to #Daniel Roseman's comment I realized I was performing the inheritance backwards. I was also over-complicating things. Using the include tag I was able to perform the sort of inheritance I was hoping to achieve very easily.
generic_create.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div style= "padding-top: 30px">
<form method="post">{% csrf_token %}
{% if model_name == 'TransactionsTable' %}
<div>
{% include "transactions_create.html" %} #NOTE: Here I removed the block and added 'include'.
</div>
{% else %}
{{ form |crispy }}
{% endif %}
<div id="container">
<input type="submit" class="btn btn-default" value="Save">
Cancel
<div>
</form>
</div>
{% endblock content %}
transactions_create.html
Hello1 #removed all of the extend and 'block' code. 'include' just renders the html directly.
That's it! 'include' really simplified things.

Related

Django allauth - Template include in base.html causes RecursionError

I am using allauth to handle all my authentication. Using that app each piece of authentication functionality is given its own template. However, I want to include the registration form in all other templates. i.e. the registration form is present in /account/login/, /account/password/change ... etc...
I decided to achieve that by including signup.html in base.html which is extended in all other templates. Like this:
base.html
...
<h4 class="card-title text-center">Register</h4>
{% include "account/signup.html" %}
...
account/base.html
{% extends "base.html" %}
account/signup.html
{% extends "account/base.html" %}
{% load i18n %}
<p>{% blocktrans %}Already have an account? Then please sign in.{% endblocktrans %}</p>
{% for message in messages %}
<span style="color:red;">{{ message }}</span>
{% endfor %}
<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
{% csrf_token %}
{% for field in form %}
<div id="input-group">
{{ field }}
</div>
{% endfor %}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<div class="card-footer text-center">
<input type="submit" class="btn" value='{% trans "Get started" %}'>
</div>
</form>
account/login.html
{% extends "account/base.html" %}
{% load static %}
{% load i18n %}
{% load account socialaccount %}
{% get_providers as socialaccount_providers %}
{% block general_notice_modal %}
{% endblock general_notice_modal %}
{% block login-modal %}
...
This code causes the following error, which only occurs when I add the {% include %} tag in base.html
I think the code below:
{% include "account/signup.html" %}
should be in "account/base.html" not in "base.html".
You have an error because your "base.html" call "account/signup.html" and your "account/signup.html" call "account/base.html" who call himself "base.html". You have a loop.

Invalid filter add_class using django-widget-tweaks

I am creating form view using django-widget-tweaks following this tutorial.
When I tried to implement add_class filter, I got following error.
Invalid filter: 'add_class'
Does anyone know how to solve this error?
html page
{% extends "base.html" %}
(% load widget_tweaks %}
{% block content %}
<form method="post" enctype="multipart/form-data">
<h4 style="margin-top: 0">Project Upload</h4>
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{hidden}}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
<label for="{{field.id_for_label}}">{{field.label}}</label>
{{field|add_class:"form-control"}}
</div>
{% endfor %}
<button type="submit">Upload</button>
</form>
{% endblock %}
form.py
class DocumentForm(forms.ModelForm):
class Meta:
model=html
fields=['project','version','diff','program','location']
You can check this-out here
{% load widget_tweaks %}
<!-- add 2 extra css classes to field element -->
{{ form.title|add_class:"css_class_1 css_class_2" }}
Try this :
{% render_field field|add_class:"form-group"%}

Reuse custom form template in django

I write a template for my form like
<h1>{% block formtitle %}{% endblock %}</h1>
<form method="post" action="">
{% csrf_token %}
[stuff]
<button type="submit">{% block formbutton %}{% endblock %}</button>
</form>
now i want to use the same template both for the creation and for the edit of an object, but how?
i tried to create a template for the creation like
{% extend "base.html" %}
{% include "form.html" %}
{% block formtitle %}Create a new MyObject{% endblock %}
{% block formbutton %}Create{% endblock %}
but i got a blank page...
You have to {% extend "form.html" %} in order to override those blocks. Blocks are overriden only for the template in the extend declarations.
A solution would be to create a new template for the new form that extends the old one:
{% extend "base.html" %}
{% include "my_form.html" %}
# my_form.html
{% extend 'form.html' %}
{% block formtitle %}Create a new MyObject{% endblock %}
{% block formbutton %}Create{% endblock %}
Or pass variables to the include statement:
{% extend "base.html" %}
{% include "form.html" with formtitle='Create new MyObject' formbutton="My button title" %}
# form.html
<h1>{% block formtitle %}{{ formtitle }}{% endblock %}</h1>
<form method="post" action="">
{% csrf_token %}
[stuff]
<button type="submit">{% block formbutton %}{{ formbutton }}{% endblock %}</button>
</form>

django 1.6 - how do I insert a class-bassed view into a template as an {% include %}

My current template structure has a home.html that extends from a base.html. That home.html file also has its own {% include %} tags that pull in from other templates (contact forms, etc).
The problem I am having is that when I use the {% include %} tag on a class based view, nothing gets rendered in my template. I can still go to the url of the class based view and it renders just fine there.
In this case frontpabe/contact.html is a typical function based view, while frontpage/skills_list.html is a class based view.
home.html:
<div class="col-lg-4">
{% block contact %}
{% include 'frontpage/contact.html' %}
{% endblock %}
{% block skills %}
{% include 'frontpage/skills_list.html' %}
{% endblock %}
</div>
contact.html:
{% block contact %}
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<input type="text" name="subject" placeholder="I want a free estimate...">
<p></p>
<input type="text" name="email" placeholder="email address (optional)">
<p></p>
<textarea name="message" placeholder="here are some things I need..."></textarea>
<br />
<input type="submit" value="Submit">
</form>
{% endblock %}
skills_list.html:
{% block skills %}
{% for item in skills_list %}
<h3 style='background-color:yellow;'> {{ item.skills }} </h3>
{% endfor %}
{% endblock %}
Your problem won't have anything to do with whether it's a function-based view or a class-based view--the {% include %} tag merely includes the template itself--it doesn't call the view. It's literally as if you just copied + pasted the text of the contact or skills templates into your front page template.
Without seeing the rest of your code, I can't be 100% sure, but a likely place for your problem is that the view class or function for your homepage doesn't have a variable skills_list or, if it does, that it is empty. So your skills_list.html template is being used, it's just rendering the results of looping over an empty list (a quick check would be to add a tiny bit of static text, like "HELLO?" to skills_list.html outside of your {% for ... %}; if you see that, you're definitely rendering the template.
If it is a missing skills_list variable, it's almost certainly because of the misunderstanding about views/templates. You're probably defining that template in the CBV associates with skills_list.html template--but, again, the {% include %} tag doesn't call your view; it just includes the raw template itself.
Extends and include are different and should not be used together. If you are going to define blocks then have the children template extend the parent and override the blocks- no includes necessary:
home.html:
<div class="col-lg-4">
{% block contact %}
{% endblock %}
{% block skills %}
{% endblock %}
</div>
contact.html:
{% extends 'home.html' %}
{% block contact %}
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<input type="text" name="subject" placeholder="I want a free estimate...">
<p></p>
<input type="text" name="email" placeholder="email address (optional)">
<p></p>
<textarea name="message" placeholder="here are some things I need..."></textarea>
<br />
<input type="submit" value="Submit">
</form>
{% endblock %}
skills_list.html:
{% extends 'home.html' %}
{% block skills %}
{% for item in skills_list %}
<h3 style='background-color:yellow;'> {{ item.skills }} </h3>
{% endfor %}
{% endblock %}
Alternatively, you could use includes:
home.html:
<div class="col-lg-4">
{% include 'frontpage/contact.html' %}
{% include 'frontpage/skills_list.html' %}
</div>
contact.html:
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<input type="text" name="subject" placeholder="I want a free estimate...">
<p></p>
<input type="text" name="email" placeholder="email address (optional)">
<p></p>
<textarea name="message" placeholder="here are some things I need..."></textarea>
<br />
<input type="submit" value="Submit">
</form>
skills_list.html:
{% for item in skills_list %}
<h3 style='background-color:yellow;'> {{ item.skills }} </h3>
{% endfor %}

How to make a reusable template in Django?

What is the Django way of creating a reusable template?
Example: Suppose a lot of my pages contain a "Latest News" box and following the DRY principle, I would like to define it once and reuse it in the other pages. How would I do this with Django (or Jinja2) templates?
Reading through Django's Template Documentation I get the impression that Django templates offer "top-down" inheritance where the sub-template itself determines in which super-template it is going to be embedded:
<!-- Super-template (not valid, for illustration): -->
<html>
<head><title>Title</title></head>
<body>{% block content %}{% endblock %}</body>
</html>
<!-- Sub-template: -->
{% extends "base.html" %}
{% block content %}
<div class="latest-news">News</div>
{% endblock %}
So what is the technique to reuse a block (a sub-template) in several places?
The most flexible way to reuse template fragments is to define an inclusion_tag. You can pass arguments to your custom tag, process them a bit in Python, then bounce back to a template. Direct inclusion only works for fragments that don't depend on the surrounding context.
Quick example from the docs:
In app/templatetags/poll_extras.py register the tag with a decoration:
from django import template
register = template.Library()
#register.inclusion_tag('results.html')
def show_results(poll):
choices = poll.choice_set.all()
return {'choices': choices}
In app/templates/results.html:
<ul>
{% for choice in choices %}
<li> {{ choice }} </li>
{% endfor %}
</ul>
Calling the tag:
{% load poll_extras %}
{% show_results poll %}
What you're looking for, is {% include "template.html"%} from Django docs.
If you need to use {% block %} you can only do that via the {% extend %} approach. Otherwise, you can use {% include 'some.html' %} to include a bit of HTML in multiple places.
The unofficial Django Reusable App Conventions recommends using these block names:
{% block title %}
{% block extra_head %}
{% block body %}
{% block menu %}
{% block content %}
{% block content_title %}
{% block header %} {% block footer %}
{% block body_id %} {% block body_class %}
{% block [section]_menu %} {% block page_menu %}
If everyone stuck to these conventions, it should make this problem easier. Follow the link to see the description of each block.
Example of using {% include %} tag
All data comes from Django back-end
Many values are passed to card_template.html using include tag in page1.html
card_template.html
<style>
.choices_div {
border-radius: 5rem;
}
.card-footer {
background-color: transparent;
border: transparent;
}
</style>
<div class="col mb-5 px-4">
<div class="card h-100 w-100 jumbotron choices_div {{ bg_color|default:'' }}">
<div class="card-body p-0">
<h3 class="card-title text-center">{{ card_title|capfirst }}</h3>
<ul class="card-text mt-3">
{% for c in card_body_list %}
<li>{{ c }}</li>
{% endfor %}
</ul>
</div>
<div class="card-footer text-center pt-4">
{% if get_post_request == 1 %}
<a class="btn btn-light" href="{{ href }}">{{ button_text }}</a>
{% else %}
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-light w-75" name="category"
value="{{ button_value }}">{{ button_text }}</button>
</form>
{% endif %}
</div>
</div>
</div>
page1.html
{% extends 'core/core.html' %}
{% block body %}
<div class="jumbotron bg-white">
<div class="container">
<div class="mb-5 text-center">
<h1>Choose user category</h1>
<h5>Once choosen, the user category cannot be changed</h5>
</div>
<div class="row row-cols-lg-2 justify-content-around">
{% for object in object_list %}
{% cycle 'bg_peacock' 'bg_sunset' 'bg_skin' 'bg_brown' as bg_color silent %}
{% include 'core/card_template.html' with card_title=object.category card_body_list=object.description get_post_request=2 button_text='Select' bg_color=bg_color button_value=object.id %}
{% endfor %}
</div>
</div>
</div>
{% endblock %}
As other answers have mentioned, the simplest approach is direct inclusion:
{% include 'mytemplate.html' %}
It is possible to modify the context of the rendered template (Or in simpler terms, to pass variables to the template) using
{% include 'mytemplate.html' with poll=poll %}
To use the traditional polls example, the template I would write would be:
<div class="stylish-poll">
{% for choice in poll.choices %} <!-- poll is a template variable -->
{% include 'choice_template.html' with choice=choice %}
{% endfor %}
</div>
Another potentially useful thing to know is that the only keyword prevents the template variable poll being passed into 'choice_template.html' which it would be by default. If you do not want the choice template to have access to {{ poll }} then the include statement looks like:
{% include 'choice_template.html' with choice=choice only %}
Documentation: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
Aïe, my fault – the answer is given in the Django Reference (and not discussed in the aforementioned Django Template Documentation)…
So: Just use {% include sub_template_name %}.
even though the question is asked years ago, any way I will show you the method that worked for me.
base.html
In your base template you need to define all of your blocks that you need to reuse in your other templates,
<html>
<head>
<meta name="description" content="{%block description%}{%endblock%}">
<meta name="keywords" content="{%block keywords%}{%endblock%}">
<title>{%block title%}{%endblock%}</title>
</head>
<body>
<!---other body stuff--->
{%block content%}
{%endblock%}
</body>
</html>
home.html
{%extends 'base.html'%}
<!--you can reuse all blocks here-->
{%block description%}Django reusable blocks, for every bage{%endblock%}
{%block keywords%}django,block, resuable,meta,title,{%endblock%}
{%block title%}django reuseable blocks for title, meta description and meta keywords{%endblock%}
{%block content%}
<div>
<h1> reuse blocks</h1>
</div>
{%endblock%}