Django Context Processor on {% include %} Templates? - django

I have a base-theme.html template with several {% include 'theme-component.html' %} tags.
I also have a context processor that provides a dict of some general items needed by the template - config, menuItems, etc.
The context_processor sends information to the base them when I include them in the base-theme.html directly, but not when I put them in the included template.
For example:
base-theme.html
<!doctype html...
{{ config.site_name }}
{% include 'menu.html' %}
</html>
The above works.
menu.html
<nav>
{% for item in menuItems %}
{{ item }}
{% endfor %}
</nav>
This does not work
Can anyone point me in the right direction as to why this is happening?

To do like that send Menu Item context from your view. Include just includes the template but using it as context you need to send the context

Related

How to add a contact form template into another template?

I'm very new to this and I'm trying to create a simple website for a company using django 2.
I'm using this template that is a single page: https://html5up.net/astral
I want to make the contact form work but I can't manage.
I've tried putting {% block %} {% endblock %} in the HTML file but it won't render the form, {% include %} renders the html file I created but not the form. I was wondering if it is possible to make the form that is already rendered work.
Thanks!
You can use Template Inheritance to do this.
You have your "base.html" parent template which has a placeholder for the form:
<html>
...
<div ... >
{% block contact-form %}
{% endblock %}
</div>
...
</html>
And your form is in "contact.html" child template:
{% extends "base.html" %}
{% block contact-form %}
<!-- contact form content -->
{% endblock %}
Then in your url patterns direct peeps to the view that renders the child "contact.html" template.
The {% extends %} tag lets the template engine know that it must first load the parent "base.html" and then fill in the appropriate block with the child "contact.html" template's content.

How to pass the context to a Django template with include?

I have started building a django project from the tutorial at https://docs.djangoproject.com/en/2.1/intro/tutorial01/
After finishing the base tutorial which creates a project with one app called "polls" I wanted to build a sort of home page that can hold many apps together. For this reason I built an app called "news" and now I'm looking at ways to compose the two apps together.
So far I'm doing so in the main 'news' template, which is called 'news/base.html' and I'm including the different apps in the code.
This is my 'news/base.html' file:
{% include 'news/index.html' %}
{% include polls_template %}
{% include 'news/footer.html' %}
The two templates 'news/index.html' and 'news/footer.html' are just html pages with no arguments, just for testing and they work fine.
The polls_template variable instead is a template variable that I create in the news.views.base function and pass to the template in the context.
This is the view snippet that does this:
def base(request):
t = loader.get_template('polls/index.html')
return render(request, 'news/base.html', {'polls_template': t})
The template is showing just fine but it shows an empty poll since there is no argument. Now my problem is that I cannot find a way to pass a context variable to this template object in order to fill it's fields.
I tried to do something like:
{% include polls_template with context=polls_context %}
But it does not work.
Ideally I would like a way to do all of that in the view because this would allow me to build the apps separately and then just use one view to gather them all and pass them to a template. Thanks in advance for any help!
Possible duplicate of Django - two views, one page (disregard the references to Ajax.) One quick note: I see what you are trying to do, but you should understand that render() is a shortcut that includes both the template loading and the HttpResponse(). You don't need to call loader() if you are using render(). Another problem with your function, you've included the template within the context dict. Please read the linked post b/c there are a number of different approaches but for the sake of completeness, here's one way to approach what you are trying to do. First, typically you'd create a 'base.html' file that would be the container for your content, it would include header, footer and possibly the messaging templates. You could then extend the base.html and include other templates.
'base.html'
<!doctype html>
<html lang="en">
<head>
{% include 'header.html' %}
<body>
{% include 'news.html' %}
{% block content %}
//to be replaced by index/polls content that extends this template//
{% endblock %}
</body>
{% include 'footer.html' %}
</html>
'index.html'
{% extends 'base.html' %}
{% block content %}
<ul>
{% for question in questions%}
<li> {{question}}</li>
{% endfor %}
</ul>
{% endblock %}
'news.html'
<ul>
{% for article in news %}
<li> {{article}}</li>
{% endfor %}
</ul>
And then your function
def index(request):
polls_questions = Question.objects.all()
newest_articles = Articles.objects.filter(post=OuterRef('pk')).order_by('-created_at')
return render(request, 'index.html', {'questions' : polls_questions, 'news': newest_articles})

Django include - using the correct include depending on the page

Hi guys I am fairly new to the Django framework and was hoping someone could assist me in my current dilemma :)
I have my base template set up for my project. I have a main-content area and a side-bar
I created a include for my side bar:
{% include "modules/include/sidebar.html" %}
The issue is that I have two different side bars that I would like to render depending on the page the user is on e.g. if the user is on the home page then use
{% include "modules/include/sidebar.html" %}
but if the user is on an article page then use
{% include "modules/include/article-sidebar.html" %}
I looked through the docs but couldn't find anything to help me solve this issue.
All and any help will be appreciate.
Create a block in your base template, something like {% block sidebar %}{% endblock %}
Then in your home page template do
{% extends 'your-base-template-name-here' %}
{% block sidebar %}
{% include "modules/include/sidebar.html" %}
{% endblock %}
And in your article template use
{% extends 'your-base-template-name-here' %}
{% block sidebar %}
{% include "modules/include/article-sidebar.html" %}
{% endblock %}
More about template inheritance here https://docs.djangoproject.com/en/1.9/ref/templates/language/#id1

Factorizing a header menu in Django template

I'm building a website using django with a header on top of every page, which basically is a menu with a few links, constant throughout the pages.
However, depending on the page you're on I'd like to highlight the corresponding link on the menu by adding the class "active". To do so, I am currently doing as follow: each page has a full menu block that integrates within a general layout, which does NOT contain the menu. For exemple, page2 would look like this:
{% extends "layout.html" %}
{% block menu %}
<li>Home</li>
<li>page1</li>
<li class="active">page2</li>
<li>page3</li>
{% endblock %}
The problem is that, beside from that solution being not so pretty, every time I want to add a link to the header menu I have to modify each and every page I have. Since this is far from optimal, I was wondering if any of you would know about a better way of doing so.
Thanks in advance!
You can create a custom templatetag:
from django import template
from django.core.urlresolvers import reverse, NoReverseMatch, resolve
register = template.Library()
#register.simple_tag
def active(request, view_name):
url = resolve(request.path)
if url.view_name == view_name:
return 'active'
try:
uri = reverse(view_name)
except NoReverseMatch:
uri = view_name
if request.path.startswith(uri):
return 'active'
return ''
And use it in the template to recognize which page is loaded by URL
<li class="{% active request 'car_edit' %}">Edit</li>
If you have a "page" object at every view, you could compare a navigation item's slug to the object's slug
navigation.html
<ul>
{% for page in navigation %}
<li{% ifequal object.slug page.slug %} class="active"{% endifequal %}>
{{ page.title }}
</li>
{% endfor %}
</ul>
base.html
<html>
<head />
<body>
{% include "navigation.html" %}
{% block content %}
Welcome Earthling.
{% endblock %}
</body>
</html>
page.html
{% extends "base.html" %}
{% block content %}
{{ object }}
{% endblock %}
Where navigation is perhaps a context_processor variable holding all the pages, and object is the current PageDetailView object variable
Disclaimer
There are many solutions for your problem as noted by Paulo. Of course this solution assumes that every view holds a page object, a concept usually implemented by a CMS. If you have views that do not derive from the Page app you would have to inject page pretenders within the navigation (atleast holding a get_absolute_url and title attribute).
This might be a very nice learning experience, but you'll probably save loads time installing feinCMS or django-cms which both define an ApplicationContent principle also.
You may use the include tag and pass it a value which is the current page.
For example, this may be a separate file for declaring the menu template only:
menu.html
{% if active = "a" %}
<li>Home</li>
{% if active = "b" %}
<li>page1</li>
{% if active = "c" %}
<li class="active">page2</li>
{% if active = "d" %}
<li>page3</li>
And call this from within your template like this:
{% include 'path/to/menu.html' with active="b"%} # or a or c or d.
Hope it helps!

Why is this django template tag failing to display?

I have a template tag located in catalog/templatetags/catalog_tags.py, which looks like this:
register = template.Library()
#register.inclusion_tag("tags/navigation.html")
def nav_links():
flatpage_list = FlatPage.objects.all()
return {'flatpage_list': flatpage_list }
I have a catalog.html which has {% load catalog_tags %}, to load that tag, and is followed by an inclusion tag for my navigation, {% include "tags/navigation.html" %}.
navigation.html contains the following:
{% with flatpage_list as pages %}
{% for page in pages %}
{{ page.title }}
{% endfor %}
{% endwith %}
But the list of flat_pages is not appearing in my navigation section. Why is that?
If I understand right, with your current state you have something liek this in catalog.html template:
{% load catalog_tags %}
.....
{% include "tags/navigation.html" %}
What this code does, is just renders the "tags/navigation.html" template, nothing more. So your custom template tag is not hit at all. To fix it, you should replace include with nav_links:
{% load catalog_tags %}
.....
{% nav_links %}
See Django docs for reference.
Not sure if it's just a copy paste error or not but return {'flatpage_list': flatpage_list isn't closed properly return {'flatpage_list': flatpage_list}
Also could this be something more suited for a context processor?
EDIT: After reading the other answer, I realized what you are trying to do, when you were using the {% include ... %} tag it seemed like you just wanted to populate the flatpage_list