Wagtail page context in Streamfield template - django

I have StructBlock with it's own template, within a StreamField. I'm trying to access the page object from said template.
{% load wagtailcore_tags article_tags %}
{% article_constants as constants %}
<div id="interactions__combo__addition" class="col-md-6">
<h3>
{% include_block page.translated_title %}
+
<span id="interactions-combo-addition-temp">?</span> =
</h3>
<div alt="dangerous to synergy bar" style="height:10px; width:100%">
</div>
</div>
<div class="interactions__combo__result col-md-5">
<h3 class="interactions__combo__result__title">
{{ constants.select_element }}
</h3>
<p class="interactions__combo__result__description">
{{ constants.none_selected_text }}
{% include_block page.colour %}.
</p>
</div>
{% include_block page.colour %} and {% include_block page.translated_title %} render nothing.
Thank you in advance for your help.

You should use the {% include_block %} tag when outputting the StreamField on your page template. For example, if your StreamField is called body, use {% include_block page.body %} on your page template. This will ensure that the context variables from the outer template (including page) are available in your StructBlock's template - if you use {{ page.body }} instead, the StructBlock template will render, but won't have access to the variables from the outer template.
Don't use {% include_block %} for fields of page that are not StreamFields, such as page.translated_title.

Related

Django CMS, there is a piece of HTML in the include, how to include this piece twice on one page and so that you can change different content?

There is a template in the include / cards folder
{% load cms_tags %}
{% load static %}
<div class="cards">
<div class="card__item">
<div class="card__top">
{% placeholder 'card__top_c1' %}
</div>
<div class="card__foot">
{% placeholder 'card__foot_c1' %}
</div>
</div>
.........
</div>
I connect this piece on one page twice, is it possible somehow that one include had one content, and the other has another ????
it just turns out if I change something in the first, then it changes in the second, what can be done ???
{% include './include/cards.html' %}
<br><br>
{% include './include/cards.html' %}
You can try using if-else. Check the snippet
Models.py
class modelname(models.Model):
position = models.CharField(max_length=50, choices=(
('Top', 'top'),
('Footer', 'foot')
))
Cards.html
{% load static %}
{% if modelname.position == 'top' %}
<div class="card" >
<div class="card__top">
{% placeholder 'card__top_c1' %}
</div>
</div>
{% else %}
<div class= "card">
<div class="card__foot">
{% placeholder 'card__foot_c1' %}
</div>
</div>
{% endif %}

Translate django variable with html template value

I am trying to translate like this:
<div class="col-sm-7 section">
{{ template |safe }}
</div>
template = <div class="row">
<div class="calc-head">{% trans "Calculations" %}</div>
</div>
But the {% trans "Calculations" %} is not working for me. Can anyone help me
Why are you using template as a variable? Did you add it to the page as a string context object?
Save your template as an html file, remember to
{% load i18n %}
on top of the file and then put your code (with html content) inside:
{% blocktrans %}
{# Your html markup here #}
{% endblocktrans %}
And then add it to the page where you need it as:
{% include 'folder/name.html' %}
I hope that helps.

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

django - Invalid block tag: 'add_pinned_status', expected 'else' or 'endif'

I get the following error when serving my django application using Nginx+FastCGI
Invalid block tag: 'add_pinned_status', expected 'else' or 'endif'
Oddly, the site works just fine when I'm serving using the Django development server. It also works with Nginx most of the time, but the error randomly appears and reappears with refreshes. Any idea what the problem could be?
EDIT: Here's the code, just to clarify that there's NO hanging if statement.
{% extends 'master.html'%}
{% load thumbnail %}
{% load tags %}
{% block 'title' %}
{{ title }}
{% endblock %}
{% block 'content' %}
<div id="feed" class="content">
{% for book in books.object_list %}
<div class="book_preview">
<div class="thumbnail">
<a href="/book/{{ book.id }}/{{ book.get_slug }}/">
{% if book.cover_image %}
{% thumbnail book.cover_image "120" as im %}
<img src="{{ im.url }}" alt="Python for Software Design"/>
{% endthumbnail %}
{% else %}
<img src="{{ STATIC_URL }}default_thumb.jpg" alt="Python for Software Design"/>
{% endif %}
</a>
</div>
<div class="book_details">
<h2 class="book_title">
<a class="book_profile_link" href="/book/{{ book.id }}/{{ book.get_slug }}/">{{ book.title }}</a>
{% if user != book.uploader %}
<a class="shelf_adder {% add_pinned_status request book.pk %}" href="/shelf/{{ book.id }}/toggle/?next={{ request.get_full_path }}" title="Toggle shelf status"></a>
{% endif %}
</h2>
<h3 class="book_subtitle">
{% if book.subtitle %}
{{ book.subtitle }}
{% else %}
<a href='/book/{{book.id}}/edit/#subtitle'>Provide subtitle</a>
{% endif %}
</h3>
<h3 class="book_authors"> by {{ book.author.filter|join:", " }}</h3>
<div class="book_description">
{% if book.description %}
<p>
{{ book.description|truncatewords:25 }}
</p>
{% else %}
<p class="message">No description available. Create one.</p>
{% endif %}
</div>
<div class="book_links">
<a href="/book/{{ book.id }}/{{ book.get_slug }}/" class="book_profile_link" title="Book profile">
Book profile
</a>
<a href="http://{{ book.homepage }}" class="book_website_link" title="Book website" target="_blank">
Book website
</a>
</div>
<p>Points: {{ book.shelf_additions }}</p>
<div class="book_tags">
{% if book.topics.all %}
{% for topic in book.topics.filter %}
{{ topic }}
{% endfor %}
{% else %}
<a href="/book/{{ book.id }}/edit/#topics" title='Click to add'>no topics added☹</a>
{% endif %}
</div>
</div>
<div style="clear: both;"></div>
</div>
{% endfor %}
<div class="pagination">
{% if books.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ books.number }} of {{ books.paginator.num_pages }}
</span>
{% if books.has_next %}
next
{% endif %}
</div>
</div>
{% endblock %}
The problem starts on the line after the if user != book.uploader statement, which as you can see is terminated with the appropriate endif. I suspect it may be some sort of timeout but I'm not entirely sure. Keep in mind, it works sometimes but randomly stops when using Nginx. It works flawlessly with the dev server.
Django gives that error when you have an unclosed templatetag. In this case an {% if ... %} templatetag.
As to why it only happens in certain scenarios, it might be inside a conditional tag itself, so it's not always processed, but I think Django processes the whole template despite what's going on conditionally or not. It might also be possible that there was some mistake in updating your production site and it's using a different/older version than your development site.
Regardless, the error is the error. Find the unclosed templatetag, and you'll solve it across the board.
UPDATE: The alternative is that the add_pinned_sites templatetag is undefined. Assuming it is in fact loaded in {% load tags %}, make sure that that templatetag library is available in all running environments, i.e. it literally exists on the server. If it is in fact there, make sure you completely reload your Nginx+FastCGI environment, or just reboot the server to be completely sure.
Is "tags" the actual name of the tag library that holds add_pinned_sites? Might be worth changing it to a clearer name-- just wondering if it's possible you're seeing import collisions between that and another tag library (like Django's built-in tags).

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).