about django templates and global variables - django

I have a skeleton.html template, and i have a archives box in my blog. So i have to update in every function in my views or there is one simple way to do that? like a global variable takes the latest and the newest post's year then i will use in my templates?
And when i extend another template like:
{% extends "base.html" %}
{% load static %}
{% block title %}{{ title }}{% endblock %}
{% block css %}<link rel="stylesheet" href="{% static "css/style.css" %}"/>{% endblock %}
{% block contentRight %}
<div id="search">
<h2>Search</h2>
<form action="#" method="POST">
<input type="text" name="searchbox"/>
<input type="submit" name="submit" value="Search"/>
</form>
</div>
<div id="archives">
<h2>Archives</h2>
<ul>
<li>2013</li>
<li>2012</li>
<li>2011</li>
</ul>
</div>
{% endblock %}
title is in my views.py home function, when i create another html file and extend index and pass the title block it loads nothing...
sry for my bad english and noobish question~im new in django

You can define your own RequestContext processor, query the years you want in years_processor:
def years_processor(request):
return {'years': range(2013, 2010, -1)}
Add it to TEMPLATE_CONTEXT_PROCESSORS, then use years directly in your every template.
<ul>
{% for year in years %}
<li>{{ year }}</li>
{% endfor %}
</ul>
Keep in mind that you should use render or pass context explictly.

Related

Djang multiple levels of template extension while keeping the elements of the upper levels

I have 3 templates as following:
base.html (the top level template, as usual).
<body>
<div id="header">
...
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
category.html :
{% extends "base.html" %}
{% block content %}
<div class="category_row">
<div id="menu_category_display">
{% for category in menu_categories %}
{% with category_button="menu_"|add:category.name|lower %}
<button class="button category_buttons {{category_button}}"
onclick="showItem('{{category_button}}','category_buttons')">
{{category}}
</button>
{% endwith %}
{% endfor %}
</div>
</div>
<div class="item_row">
{% block level_2_content %}
{% endblock %}
</div>
{% endblock %}
and item.htlm
{% extends "menu/category.html" %}
{% block level_2_content %}
<div id="test_div">
{% for item in menu_items %}
<p>{{item.name}}</p>
{% endfor %}
</div>
{% endblock %}
When item.html is rendered, all the elements that were rendered by category.html are gone. Only the elements of the base.html are retained.
How do I retain all elements in all parent templates instead of just base.html? A general method to do this for more than 3 levels of extension like in my case?
Update with more detailed code for category.html. The entire category_row div does not appear in item.html. How do I retain them?
views.py
def menu_category_view(request, table_pk):
menu_categories = Category.objects.all()
menu_items = Item.objects.filter(available=True)
return render(request,
'menu/category.html',
{'menu_categories': menu_categories,
'menu_items': menu_items,
'table_pk': table_pk})
def menu_item_view(request, menu_category, table_pk):
category = Category.objects.get(name=menu_category)
menu_items = Item.objects.filter(available=True,
category=category.pk)
return render(request,
'menu/item.html',
{'menu_items': menu_items})
Folder structure: both templates sit in menu/templates/menu of app menu. However, base.html sits in root/templates (not in app menu.
Update: I have tried modifying both templates in various ways to debug. What I find is that the static content gets extended, but the dynamic content does not. So my question becomes: does Django template allow dynamic content to be extended to child / grandchild templates?
You probably don't want to use "extends" here but instead "include" to render 'item.html' within the parent document.

Why does template inheritance in Django not show error?

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.

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 %}

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%}

Unable to paginate object_list usng django-pagination

I am using django-pagination to paginate the a list of objects in my temlate. I have installed the app, added it in my project and added pagination.middleware.PaginationMiddleware in my settings.py file. But when I try to use it in my template the object_list is not being paginated. Here is my template code
{% extends "base.html" %}
{% load pagination_tags %}
{% autopaginate Questions %}
{% block title %}
Questions
{% endblock %}
{% block content %}
<div id="contentDiv">
{% for question in Questions %}
<div style="padding:5px 20px 5px 30px;">
<p class='question'><span id='style2'>Q
</span> {{ question.questiontext|safe }}
<span style= 'float:right;'><span style='font-size:12px; color:#099;'><a href="/question/type={{question.type}}"
style='font-size:12px; color:#099;'>{{question.type}}</a></span> <span style='color:#99C; font-size:12px;'>Level: </span><span style='color:#099;font-size:12px;'>{{question.level}}</a></span></span>
</p>
<h2 class='trigger1' ><a href='#'>Answer</a></h2>
<div class='toggle_container' >
<div class='block' style='background-color:#fff; '>
<p class='ans'> {{ question.answer|safe }} </p>
</div>
</div>
</div>
{% endfor %}
<div class="pagination" style="width:1000px; margin:auto; margin-bottom:20px;">
{% paginate %}
</div>
</div>
{% endblock %}
The list of objects is in the context_variable called Questions. Am I doing something wrong?
After a very long time I have been able to find out the error I was having with django-pagination. I had the canonical base template which I was extending on all pages.
In the documentation it is written that we require to put {% paginate %} after {% autopaginate object_list %} but no where it was written about the placement of {% autopaginate object_list %} itself.
I had title and body blocks in my template, and I was putting {% autopaginate object_list %} just below the {% extends "base.html" %} and as a result it was not working. I found that I had to put this statement inside the body block and now it is working absolutely fine.
Can you see the content of your pagination div if you write "Hello, I want a burger" or anything else in there?
Are you sure you have enough Questions to paginate? You could try something like:
{% autopaginate Questions 2 %}
to make sure that you'll be paginating at 2 questions/page.
Solved as Sachin told above:
I just moved {% load pagination_tags %}{% autopaginate list_objs 10 %}
inside {% block content %} statement (previously it was outside of it, so pagination was invisible. If no errors, but now pages - try to play with it (moving pagination block).