Django: Add class to a div depending on a variable - django

I'd like to declare in the template a variable that allows me to position an image inside a section on the left or the right. I just don't understand how can I do it on the variable side.
Here's my current code,
main.html :
{% with img_left=False %}
{% include 'section-service.html' %}
{% endwith %}
section-service.html:
<div class="sect_service-inside {% if img_left=True %} serv_img-left {% else %} serv_img-right {% endif %}">
<div id="here_img">...</div>
<div id="here_text">...</div>
</div>
but I get the error Could not parse the remainder: '=True' from 'img_left=True'
Note that I'll use this section multiple times in the main.html page, that's why I'd like to have the variable left-right.
EDIT:
views.py:
def page(request):
return render(request, 'main.html')

I suppose you want widget-tweaks
As example for form:
{% for field in form %}
{% if <something> %}
{% render_field field class="<first class>" %}
{% elif <something other> %}
{% render_field field class="<second class>" %}
{% else %}
{% render_field field class="<other class>" %}
{% endif %}
{% endfor %}

Related

in django template unable to show content inside if block

when i write if statement nothing show in html but when i remove the if statement the code show all items what is wrong
{% for catagory in catagory_list %}
{% for item in product_list %}
{% if item.catagory == "Fruits" %}
<p>{{item.catagory}}</p>
<p>{{item.name}}</p>
<p>{{item.price}}</p>
<img src="{{item.image.url}}" alt="">
{% endif %}
{% endfor %}
{% endfor %}
Because catagory is an Object, Try:
{% if item.catagory.name == "Fruits" %}
assuming that catagory model has an attribute "name"

django tables how to detect if table is empty

I am new to django and web development and based on examples and help on SO, I have pieced together something which takes a model and renders it in a django-table. My template code is basically as follows:
{% block content %}
{% load static %}
{% load render_table from django_tables2 %}
<div class="function-page">
<div class="table-form">
<div class="function-container">
{% render_table reviews %}
</div>
</div>
</div>
{% endblock %}
The view is as follows:
#login_required(login_url="login/")
def review(request):
table = DummyTable(DummyModel.objects.all())
form = DummyForm()
RequestConfig(request, paginate={"per_page": 10}).configure(table)
return render(request, 'review.html', {'reviews': table, 'DummyForm': form})
This works fine. However, what I would like to do is show a message to the user saying that there are no records when the database table is empty. In the current setting, it shows an empty table with the columns which is probably not the best from a usability point of view.
There are two options. Either you set empty_text inside class Meta
class Reviews(tables.Table):
class Meta:
empty_text = _("There are no reviews yet")
Or you can check it inside the template and avoid rendering table this way
{% if reviews_table.data.list %}
{% render_table reviews_table %}
{% else %}
<h1>There are no reviews yet</h1>
{% endif %}
Probably the easiest way is in your template. Assuming your variable that's empty is called reviews:
{% block content %}
{% load static %}
{% if reviews %}
{% load render_table from django_tables2 %}
<div class="function-page">
<div class="table-form">
<div class="function-container">
{% render_table reviews %}
</div>
</div>
</div>
{% else %}
<span> Whatever holding response/error message you want. </span>
{% endif %}
{% endblock %}
Per this this answer, for example, using {% if variable %} against a valid but empty variable, it generally evaluates to False, letting you use the {% if reviews %}.
However, if you need a really bulletproof check, you can do {{ value|default:"nothing" }} - from here.
You could also do it in your views, and pass an error message back to the template using the standard Messages framework included in Django:
from django.contrib import messages
messages.add_message(request, messages.INFO, "No reviews found, I'm afraid!.")
You need to include something like this in your templates to use messages:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
Or you could do both! :)
test against table.paginated_rows it will be empty and evaluated to False when the table have no data.
they use this in django_tables2/templates/django_tables2/bootstrap.html:~26 template:
{% for row in table.paginated_rows %}
...
{% empty %}
... {{ table.empty_text }}
{% endfor %}
Do this:
{% if reviews %}
<div class="function-page">
<div class="table-form">
<div class="function-container">
{% render_table reviews %}
</div>
</div>
</div>
{% else %}
<div>
<p> Message to use </p>
</div>
{% endif %}
Milano answer worked to me, but removing ".list" from the if conditional:
{% if reviews_table.data.list %}
{% render_table reviews_table %}
{% else %}
<h1>There are no reviews yet</h1>
{% endif %}

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.

Django template conditional variable assignment

I want to assign a variable do different values depending on if a variable exists, is this possible? My non working example might make it clearer:
{% if username %}
{% with menu_user=username %}
{% elif recent_users %}
{% with sorted_users=recent_users|dictsortreversed:"timestamp" %}
{% with menu_user=sorted_users.0.username %}
{% endif %}
{% if menu_user %}
<div id="menu">
<ul>
<li>Profile</li>
<li>Products</li>
</ul>
</div>
{% endif %}
{% if recent_users %}
{% endwith %}
{% endif %}
{% endwith %}
Pseudocode of what I try to do:
if username:
menu_user = username
elif recent_users:
menu_user = sorted(recent_users)[0]['username']
if menu_user:
<div id="menu">
<ul>
<li>Profile</li>
<li>Products</li>
</ul>
</div>
update
Then its better to customize a template tag like
#register.inclusion_tag('menu_snippet.html') # or you could use takes_context=True and fetch values from the context
def render_menu(username, recent_users):
if username:
menu_user = username
elif recent_users:
# sorted here could be replaced by min or QuerySet method, it depends
# for example:
# menu_user = min(recent_users, key=lambda u:u.timestamp).username
menu_user = sorted(recent_users)[0]['username']
return {'menu_user':menu_user}
# in template, it looks like
{% render_menu username recent_users %}
Putting the code in the view is much better. Just as your pseudocode, clean and readable.
If you still want to write template, I prefer something like
{% if username %}
<div id="menu">
<ul>
<li>Profile</li>
<li>Products</li>
</ul>
</div>
{% else %}
{% if recent_users %}
{% with sorted_users=recent_users|dictsortreversed:"timestamp" %}
{% with menu_user=sorted_users.0.username %}
<div id="menu">
<ul>
<li>Profile</li>
<li>Products</li>
</ul>
</div>
{% endwith %}{% endwith %}
{% endif %}
{% endif %}
Depends on your actual usage, customized template tag or the include tag are also possibly useful.
Template tag:
#register.assignment_tag
def alias(obj):
"""
Alias Tag
"""
return obj
Template:
{% alias sorted_users.0.username as menu_user %}
Create a template tag that takes username and recent_users as arguments which then outputs the menu. That way you will keep your template clean from that kind of logic.

How can I get a variable passed into an included template in django

I am a Django newbie and am unable to achieve something trivial. Please help me with this.
I am setting a variable pgurl in my views.py
Am able to access the variable {{pgurl}} in my with_tag.html template. This template includes a pagination.html template into itself
In pagination.html I am unable to use the variable {{pgurl}} and nothing is printed
How can I get this variable passed into the included template?
views.py
def with_tag(request, tag, template_name='main/with_tag.html', current_page=1, pgurl=''):
if request.method == 'GET':
query_tag = Tag.objects.get(name=tag)
primes = TaggedItem.objects.get_by_model(Prime, query_tag)
primes = primes.order_by('-date')
request.page = current_page
tcm_pp = TCM_ITEMS_PER_PAGE
pgurl = request.path
else:
return HttpResponseRedirect(request.path)
return direct_to_template(request, template_name, { 'primes' : primes, 'prime_total' : Prime.objects.count(), 'now': datetime.now(), 'page' : current_page, 'tcm_pp' : tcm_pp, 'tag' : tag, 'pgurl' : pgurl })
with_tag.html
{% extends "base.html" %}
{% load comments %}
{% load pagination_tags %}
...
{% include "pagination.html" %}
{% paginate %}
pagination.html
{% if is_paginated %}
{% load i18n %}
<div class="pagination">
{% if page_obj.has_previous %}
‹‹ {% trans "previous" %}
{% else %}
<span class="disabled prev">‹‹ {% trans "previous" %}</span>
{% endif %}
{% for page in pages %}
{% if page %}
{% ifequal page page_obj.number %}
<span class="current page">{{ page }}</span>
{% else %}
{{ page }}
{% endifequal %}
{% else %}
...
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
{% trans "next" %} ››
{% else %}
<span class="disabled next">{% trans "next" %} ››</span>
{% endif %}
</div>
{% endif %}
It will be helpful if you post the output of the rendered page. The context should get passed, might be your template tags instead. Try to do assert and check to see if the variables were passed correctly.