Global variables not defined in {% set %} - python

I have the following:
layout.html
{% if enableEntry or enableExit %}
{% from "cp.layout.html" import entry, exit %}
{% endif %}
<!DOCTYPE html>
<html lang="en">
<body>
{% if enableEntry %}{{ entry }}{% endif %}
{% if enableExit %}{{ exit }}{% endif %}
{% block body %}{% endblock %}
</body>
</html>
cp.layout.html
{% set entry %}
...
{% if offer.text_id == "mcd" %}
Mcdonald
{% elif offer.text_id == "bk" %}
Burger King
{% endif %}
...
{% endset %}
in my view:
def test():
.... (offer is defined here) ...
return render_template('layout.html', offer=offer)
I am getting an error that UndefinedError: 'offer' is undefined
Is there a way to pass variables that have global scope in the view to {% set %} blocs?

Seems like you never include your test.html under layout.html
I not sure is this help, this is my jinja 2 template design u can try
layout.html
{%- extends "test.html" %}
{# {% include "test.html" %} #}
{% block content %}
{{ super() }}
{%- endblock %}
test.html
{% block content %}
<div>
<h1>{{ offer }}</h1>
</div>
{% endblock %}
Let me know is this method work will give more explanation later

Related

django changeform_view extra_context

I'm trying to learn on model admin template customization.
I need that custom template can read some data stored/passed in 'extra_context'
admin.py
from django.contrib import admin
from .models import MailTemplate
# Register your models here.
class MailTemplateAdmin(admin.ModelAdmin):
change_form_template = 'change_form_htmx.html'
def changeform_view(self,request, object_id=None, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['myvar']='this is myvar'
return super(MailTemplateAdmin, self).changeform_view(request, object_id=object_id, form_url=form_url, extra_context=extra_context)
admin.site.register(MailTemplate,MailTemplateAdmin)
template 'change_form_htmx.html'
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_modify %}
{% block extrahead %}{{ block.super }}
<script src="{% url 'admin:jsi18n' %}"></script>
{{ media }}
{% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" href="{% static "admin/css/forms.css" %}">{% endblock %}
{% block coltype %}colM{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
{% translate 'Home' %}
› {{ opts.app_config.verbose_name }}
› {% if has_view_permission %}{{ opts.verbose_name_plural|capfirst }}{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
› {% if add %}{% blocktranslate with name=opts.verbose_name %}Add {{ name }}{% endblocktranslate %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
</div>
{% endblock %}
{% endif %}
{% block content %}<div id="content-main">
<!--- add htmx -->
<script src="https://unpkg.com/htmx.org#1.6.0"></script>
{% block object-tools %}
{% if change and not is_popup %}
<ul class="object-tools">
{% block object-tools-items %}
{% change_form_object_tools %}
{% endblock %}
</ul>
{% endif %}
{% endblock %}
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}" {% endif %}method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
<div>
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
{% if errors %}
<p class="errornote">
{% blocktranslate count counter=errors|length %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktranslate %}
</p>
{{ adminform.form.non_field_errors }}
{% endif %}
{% block field_sets %}
{% for fieldset in adminform %}
{% include "admin/includes/fieldset.html" %}
{% endfor %}
{% endblock %}
{% block after_field_sets %}{% endblock %}
{% block inline_field_sets %}
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
{% endblock %}
<div id="some_buttons">
<!-- here we have button for add and delete row-->
from extra_context = {{ extra_context.myvar }}
</div>
{% block after_related_objects %}{% endblock %}
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
{% block admin_change_form_document_ready %}
<script id="django-admin-form-add-constants"
src="{% static 'admin/js/change_form.js' %}"
{% if adminform and add %}
data-model-name="{{ opts.model_name }}"
{% endif %}
async>
</script>
{% endblock %}
{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}
</div>
</form></div>
{% endblock %}
There is no error occured, but the extra_content['myval'] is not showed.
Kindly please tell how is the proper way to send extra_context from ModelAdmin and read it in template.
Sincerely
-bino-
Argghh my vault.
It work now.
I replace (in template)
{{ extra_context.myvar }}
with
{{myvar}}

Django assignment_tag conditional

I'm trying to show partials based on a simple condition. My condition is whether an assignment_tag is True or False.
Templatetag:
from django import template
register = template.Library()
#register.assignment_tag
def partner():
return False
Template:
{% load partner_check %}
{% if partner %}
{% block header %}
{% include 'includes/partner_header.djhtml' %}
{% endblock header %}
{% block footer %}
{% include 'includes/partner_footer.djhtml' %}
{% endblock footer %}
{% endif %}
No matter what I set partner to, the blocks still appear. What am I missing?
Firstly, that's not how assignment tags work. You have never actually called the tag; if partner refers to a (non-existent) template variable named "partner". You call an assignment tag by using it on its own along with a variable to assign it to:
{% partner as partner_value %}
{% if partner_value %}...{% endif %}
Secondly, that's not how blocks work either. You can't dynamically define blocks; they are part of the basic structure of a template, not something that is assigned during evaluation.
I accomplished this by using a context_processor (https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-TEMPLATE_CONTEXT_PROCESSORS)
Context Processor:
def partners(context):
return {
'partner': False
}
Template:
{% block header %}
{% if partner %}
{% include 'includes/partner_header.djhtml' %}
{% else %}
{{ block.super }}
{% endif %}
{% endblock header %}
{% block footer %}
{% if partner %}
{% include 'includes/partner_footer.djhtml' %}
{% else %}
{{ block.super }}
{% endif %}
{% endblock footer %}

Jinja2 templates inheritance

With Jinja2, do all blocks need to be defined in the base template from which all other templates extend? For instance, given the following templates:
<-- ultra_base.j2 -->
<head>
</head>
<body>
{% block content %}{% endblock %}
{% block extra_js %} {% endblock %}
</body>
and
<-- child.j2 -->
{% extends ultra_base %}
{% block extra_js %}
<script src="somefile.js">
{% endblock %}
{% block page_js %} {% endblock %}
and
<-- grandchild.j2 -->
{% extends child %}
{% block content %}
<h2> Grandchild Content </h2>
{% endblock content %}
{% block page_js %}
<script src="grandchild.js"></script>
{% endblock page_js %}
The page_js block is never rendered. Is there some way to render it without changing ultra_base?
You could render page_js by putting the {% block page_js %} {% endblock %} inside the extra_js block in child.j2:
<-- child.j2 -->
{% extends ultra_base %}
{% block extra_js %}
<script src="somefile.js">
{% block page_js %}
{% endblock %}
{% endblock %}
The problem is that the page_js block in child.j2 is "in the middle of nowhere", it does not alter any block of the ulta_base.j2, so Jinja2 will not render anything from it. The solution is quite simple, you don't even need to define a new extra_js block, just use Jinja2's super() function:
ultra_base.j2 remains the same:
<!-- ultra_base.j2 -->
<head>
</head>
<body>
{% block content %}{% endblock %}
{% block extra_js %} {% endblock %}
</body>
the child.j2 template:
<!-- child.j2 -->
{% extends ultra_base %}
{% block extra_js %}
{{ super() }}
<script src="somefile.js"></script>
{% endblock %}
and the grandchildj2:
<!-- grandchild.j2 -->
{% extends child %}
{% block content %}
<h2> Grandchild Content </h2>
{% endblock content %}
{% block extra_js %}
{{ super() }}
<script src="grandchild.js"></script>
{% endblock extra_js %}
Jinja2 will take care of including block contents from the parent templates.

Rendering Django template from withing template

So, I have a number of objects I wish to render in a loop. I.E. Render each of the 5 latest posts on the home page. Each of these posts will be displayed differently whether or not the user is logged in.
I have a question: How would I go about making this distinction? I imagine having a template like this
{% if user.is_logged_in %}
{% for post in latest_posts %}
post.render_long_form
{% endfor %}
{% else %}
{% for post in latest_posts %}
post.render_short_form
{% endfor %}
{% endif %}
How can I make the functions render_short_form and render_long_form return the appropriate HTML snippits? I would like them to call other templates for rendering under the hood.
Thanks!
Why don't not use {% include %} tag?
{% if user.is_logged_in %}
{% for post in latest_posts %}
{% include 'long_form.html' %}
{% endfor %}
{% else %}
{% for post in latest_posts %}
{% include 'short_form.html' %}
{% endfor %}
{% endif %}
Or, more DRY version:
{% for post in latest_posts %}
{% if user.is_logged_in %}
{% include 'long_form.html' %}
{% else %}
{% include 'short_form.html' %}
{% endif %}
{% endfor %}

Override a block from an include via extend is blank?

So I have a base template, which includes a header:
base.html:
{% include "header.html" %}
header.html:
<ul>
<li><a>Link</a></li>
<li><a>Link</a></li>
<li><a>Link</a></li>
</ul>
{% block diskspace %}Test{% endblock %}
Then I would like to override the diskspace block from a template which extends the base, for instance:
album.html:
{% extends "base.html" %}
{% block diskspace %}
<p>You need more space!</p>
{% endblock %}
Unfortunately however diskspace only contains "Test" and is not overridden.
Is what I'm attempting possible, or do I need to go another route?
SOLUTION
Based on sergzach's answer below, here's what I ultimately implemented:
header.html:
<ul>
<li><a>Link</a></li>
<li><a>Link</a></li>
<li><a>Link</a></li>
</ul>
{% if show_diskspace %}
<p>You need more space!</p>
{% endif %}
base.html
{% block header %}
{% include "header.html" %}
{% endblock %}
album.html
{% extends "base.html" %}
{% block header %}
{% include "header.html" with show_diskspace="True" %}
{% endblock %}
header.html:
<ul>
<li><a>Link</a></li>
<li><a>Link</a></li>
<li><a>Link</a></li>
</ul>
{{diskspace}}
base.html
{% block header %}
{% include "header.html" with diskspace='Test'%}
{% endblock %}
album.html
{% extends "base.html" %}
{% block header %}
{% include "header.html" with diskspace='<p>You need more space!</p>'|safe %}
{% endblock %}

Categories