Share variables to included templates in django - django

In views.py the thing object is being passed to index.html.
def index(request):
return render(request, "myapp/index.html", {
'things': Thing.objects.all()
})
index.html is setup like this:
{% block body %}
{% for thing in things %}
{{ thing.attribute }}
<button type="button" class="btn" data-toggle="modal" data-target="#exampleModal"></button>
{% endfor %}
{% endblock %}
I would like to separate the html that renders the modal referred to by the button into another html file to keep things organized. I was able to do this by referencing the modal html file with include as shown below:
{% block modal_code %}
{% include 'myapp/modal_code.html' with things=things %}
{% endblock %}
When I tried to share the things object it didn't get incorporated into modal_code.html when I used it like this:
{% for thing in things %}
{{ thing.attribute }}
{% endfor %}

from the documentation, you can pass context like this
{% include "name_snippet.html" with person="Jane" greeting="Hello" %}
so in your case:
{% block modal_code %}
{% include 'myapp/modal_code.html' with things=things %}
{% endblock %}

Related

Failed template inheritance in django templating

I am in a middle of a project. The project uses basic html at the frontend. I having trouble in template inheritance.
This is the basic code : -
{% extends 'main.html' %}
{% block content %}
<h2>Home</h4>
<hr>
{% if request.user.is_authenticated %}
{% block home %}{% endblock home %}
{% else %}
{% for doc in doctor %}
<div>
<small>Doctors around</small>
<br>
<li>{{doc.user.name}}</li>
<br>
</div>
{% endfor %}
{% endif %}
{% endblock content %}
Also the code is extended to another template.
The child page is :-
{% extends 'rec/home.html' %}
{% block home %}
<div>
{% if request.user.usertype == 'p' %}
<h1>Hi {{request.user.name}} </h1>
{% else %}
<h1>Hi {{request.user.name}} </h1>
{% endif %}
</div>
{% endblock home %}
Both the files are in the same directory. But i have defined the templates dir in settings file in a different directory.
When i do tree /a at the templates directory this is what i get :-
Folder PATH listing
Volume serial number is 6A82-72DF
E:.
\---rec
It's just {% endblock %} you don't have to specify what block you're closing / I'm not sure you even can Wrong
That's the only issue I see with what's provided
Instead of defining the template to extend from in each template, maybe try doing something like this:
Template.html
{% extends parent_template %}
Views.py
template = loader.get_template('app/page.html')
context = {}
context["parent_template"] = "app/parentPage.html"
return HttpResponse(template.render(context, request))
This way you can assign the template from the Django side and it should be easier to troubleshoot

Django template within a for loop

I have a for loop that looks like this:
<ul>
{% for post in latest_post_list %}
<li>{{ post }}</li>
</ul>
{% empty %}
<p>No posts are available.</p>
{% endfor %}
But I want to wrap each post object in a template, so for example:
{% for post in latest_post_list %}
{% include 'jobposttemplate.html' %}
{% empty %}
{% include 'noposts.html' %}
{% endfor %}
jobposttemplate.html will then include all the various information held within the JobPost model.
I tried:
{% for jobposttemplate.html in latest_post_list %}
{{ jobposttemplate.html }}
{% empty %}
{% include 'noposts.html' %}
{% endfor %}
But, predictably, it didn't work. Basically I'm just trying to avoid having to having to write the html out each time, e.g.:
{% for post in latest_post_list %}
<div style="blah">{{ post.deadline }}
</div>
<div style="schmah">{{ post.created_at }}
</div>
{% empty %}
<p>No posts are available.</p>
{% endfor %}
If you are using app specific subfolders inside your templates/ directory, you need to add them to the file name here too.
{% include 'myapp/jobposttemplate.html' %}
And if you want the template to have access to variables, you can add them to the template's scope using with. The sub-template also has access to all scope variables too.
{% include 'myapp/jobposttemplate.html' with object=post %}

Wagtail Index page not displaying objects of children

I am at my wits-end and feel I am missing something simple but I've looked at it over and over and can't figure it out.
I have a simple person_index_page that I want to show the child person_page objects, but no matter what I try...nothing. I have several sites with a similar setup and they work. Can you please look at my code below and see if you notice something I am missing? Thank you.
home_tags.py
# Person feed for home page and staff page
#register.inclusion_tag(
'home/tags/person_listing_homepage.html',
takes_context=True
)
def person_listing_homepage(context, count=3):
people = PersonPage.objects.live().order_by('?')
return {
'people': people[:count].select_related('feed_image'),
'request': context['request'],
}
person_index_page.html
{% extends 'base.html' %}
{% load wagtailcore_tags wagtailimages_tags home_tags %}
{% block content %}
...
{% include "home/tags/person_listing_homepage.html" %}
...
{% endblock %}
person_listing_homepage.html probably should name this at some point
{% for person in people %}
{% include "home/includes/person_list_item.html" %}
{% endfor %}
person_list_item.html
{% load wagtailcore_tags wagtailimages_tags %}
{# Individual person item in a list - used on people index and home page #}
<a class="list-group-item" href="{% pageurl person %}">
<div class="media">
{% if person.feed_image %}
<div class="media-left">
{% image person.feed_image width-200 as img %} <img class="media-object" src="{{ img.url }}"/>
</div>
{% endif %}
<div class="media-body">
<h4 class="media-heading">{{ person.first_name }} {{ person.last_name }}</h4>
{% if person.search_description %}
<p>{{ person.search_description }}</p>
{% endif %}
</div>
</div>
</a>
This is more of a "how to debug" question than a Wagtail one. Rather than just giving you the answer directly, here's the process I would take:
You say that adding print(people) inside the person_listing_homepage function doesn't display anything. So, your next question should be: "is this function being run at all?" Change the print statement to print("GOT HERE"). You'll find that this doesn't display anything either - which tells you that the function is not being run.
The next step would be to add some debugging output around the place where the function should be called from - if that doesn't get displayed either, you know that code isn't being run either, and you'd have to keep going up a level until you find something that is being run. So let's look for that place...
And this is where you find the problem. You never call the person_listing_homepage function anywhere in your code. You include the person_listing_homepage.html template, but that's not the same thing. person_index_page.html should become:
{% extends 'base.html' %}
{% load wagtailcore_tags wagtailimages_tags home_tags %}
{% block content %}
...
{% person_listing_homepage %}
...
{% endblock %}

Is there a way to pass a variable to an 'extended' template in Django?

I want to add some flexibility to my layout template, but I can't find any way to do so.
I'm looking for a way to extend my layout template with variable, i.e. to pass a variable up in the template tree, not down.
# views.py
def my_view_func(request):
return render(request, "child.html")
# child.html
{% extends 'layout.html' with show_sidebar=True sidebar_width_class="width_4" %}
<div>Templates stuff here</div>
# layout.html
{% if show_sidebar %}
<div class="{{ sidebar_width_class }}">
{% block sidebar %}{% endblock %}
</div>
{% endif %}
I have to maintain four templates with a difference in a few lines of code. For example, I have two templates that differ from each other by a sidebar width class. Am I doing something wrong?
I suspect that block is what you are looking for in the first place.
Form your block inside the base template like this:
{% block sidebar_wrapper %}
{% if sidebar %}
<div class="width{{sidebar_width}}">
{% block sidebar %}{% endblock %}
</div>
{% endif %}
{% endblock sidebar_wrapper%}
And on your child template:
{% extends 'layout.html' %}
{% block sidebar_wrapper %}
{% with sidebar=True sidebar_width=4 %}
{{ block.super }}
{% endwith%}
{% endblock sidebar_wrapper%}
What you need is an include template tag. You can include a template in another template and render that with specific context.
{% include 'layout.html' with sidebar=True sidebar_width=4 %}
Check docs here: https://docs.djangoproject.com/en/2.2/ref/templates/builtins/#include
You can achieve this with some technique. I'll show the code then explain below.
# layout.html
{% block content %}
{% if show_sidebar %}
<div class="{{ sidebar_width_class }}">
{% block sidebar %}{% endblock %}
</div>
{% endif %}
{% endblock %}
# child.html
{% extends 'layout.html' %}
{% block content %}
{% with show_sidebar=True sidebar_width_class="width_4" %}
{{ block.super }}
{% endwith %}
{% endblock %}
In layout.html, wrap everything inside {% block content %}
In child.html, {{ block.super }} is like python's super(), which renders everything in the parent template's block. So if you wrap it inside {% with %} tag, all variables that you declare there will be available inside the parent template as well.

Do I need to create separate forms for simple and Ajax thing in Django

I have many forms which are working fine if i load them via normal http link.
The template is below
{% extends "app/base.html" %}
{% block title %}Create Account{% endblock %}
{% block media %} {% include "app/media_template.html" %} {% endblock %}
{% block heading %}Form{% endblock %}
{% block content %}
<div id="stylized" class="myform">
<form action="" method="post" enctype="multipart/form-data" >
<h1>Account form</h1>
<p>This is the basic look of my form without table</p>
{% csrf_token %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}
<button type="submit">Sign-up</button>
<div class="spacer"></div>
</form>
</div>
{% endblock %}
But if i have to display via ajax then i just need the div box containing form only , i don't nedd all other html
So i want that if JS is not working then those forms still work via hyperlink.
I have 6 forms , do i have to create seoarate templae if i call via ajax
If you need to use part of your template in several places, you can put that part in a separate template, and include it wherever you need:
{% include "foo/bar.html" %}
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#include