Difference between IF in Python vs Template block? [duplicate] - python

Trying to use nested block and for loop in a Jinja template block setup.
{% block main %}
<table>
<tr>
<td>user id</td>
<td>user sec level</td>
</tr>
{% block main_nested_b scoped %}
{%
for user in list_users:
t_id_user = str(user[0][0])
t_sec_level = str(user[2][0])
%}
<tr>
<td>
<a href='/usersEdit?id_user={{ t_id_user }}' class='onwhite'>edit</a>
</td>
</tr>
{% endfor %}
{% endblock main_nested_b %}
{% endblock main %}
</table>
Error message:
jinja2.exceptions.TemplateSyntaxError: expected token 'end of statement block', got 't_id_user'
Help?

You can't treat Jinja syntax as Python syntax. It's not the same thing. Keep your for tag separate from assignment (set) tags:
{% for user in list_users %}
{% set t_id_user = user[0][0] %}
{% set t_sec_level = user[2][0] %}
Note that there isn't even a : at the end of the for ... in ... syntax! Also you don't need to call str() here, leave that to Jinja to convert to strings for you; anywhere you use {{ t_id_user }} or {{ t_sec_level }} the value will be converted to a string anyway.
Here is the complete template:
<table>
{% block main %}
{% block main_nested_b scoped %}
{% for user in list_users %}
{% set t_id_user = user[0][0] %}
{% set t_sec_level = user[2][0] %}
<tr>
<td>
<a href='/usersEdit?id_user={{ t_id_user }}' class='onwhite'>edit</a>
</td>
</tr>
{% endfor %}
{% endblock main_nested_b %}
{% endblock main %}
</table>

Related

Django Form as a Table

The following code in the django template language is working but i don't know why. The purpose of this code is to display a form as a table with a number of columns. The first thing that throws me of is that the tag for opening a row is never giving but it is still made.
{% extends 'base.html' %}
{% load render_table from django_tables2 %}
{% block content %}
<form method="get">
{% csrf_token %}
<table>
<tbody>
{% for field in filter.form %}
<td>{{ field.label}}</td>
<td>{{ field }}</td>
{% if forloop.counter|divisibleby:"4"%}
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<input type="submit" value="Search">
</form>
{% render_table table%}
{% endblock %}
This generates a four column table. Is there any way the opening tags can be explicitly declared?And why is this code working?
I have tried to explicitly create the tags for row explicitly but this didn't not create the table correctly.It had an empty row space and a extra row.
{% extends 'base.html' %}
{% load render_table from django_tables2 %}
{% block content %}
<form method="get">
{% csrf_token %}
<table>
<tbody>
{% for field in filter.form %}
{% if forloop.counter|divisibleby:"5"%}
<tr>
{% endif %}
{% if forloop.counter|divisibleby:"5" == False %}
<td>{{ field.label}}</td>
<td>{{ field }}</td>
{% endif %}
{% if forloop.counter|divisibleby:"5"%}
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<input type="submit" value="Buscar">
</form>
{% render_table table%}
{% endblock %}
Why is this working? HTML is pretty lax and browsers can infer what you're trying to do with the context. td before a tr, there should be a row before -> add one
any way the opening tags can be explicitly declared? I believe with a combination of what you have and {% forloop.first %} + {% forloop.last %} this can be done.
Something along the lines of:
<table>
<tbody>
{% for field in filter.form %}
{% if forloop.first %}
<tr>
{% endif %}
<td>{{ field.label}}</td>
<td>{{ field }}</td>
{% if forloop.last %}
<tr>
{% elif forloop.counter|divisibleby:"4"%}
</tr>
<tr>
{% endif %}
{% endfor %}
</tbody>
</table>
Thanks I have put the following code which also works. I think it is now more deliberate. The first if creates the opening tag since the next tag should be a pair generated from the divisible these are in the elif the if contains the last tag which should be a closing tag alone since if it where a divisible pair of tags it would create a extra row.
{% extends 'base.html' %}
{% load render_table from django_tables2 %}
{% block content %}
<form method="get">
{% csrf_token %}
<table>
<tbody>
{% for field in filter.form %}
{% if forloop.first %}
<tr>
{% endif %}
<td>{{ field.label}}</td>
<td>{{ field }}</td>
{% if forloop.last %}
</tr>
{% elif forloop.counter|divisibleby:"4"%}
</tr>
<tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<input type="submit" value="Buscar">
</form>
{% render_table table%}
{% endblock %}

Can a child template also use a child template in django?

My child template path is project/sales/templates/sales/table.html.
It extends another child template sale_summary_change_list.html.
{% extends 'sales/sale_summary_change_list.html' %}
{% block result_list %}
<div class="results">
<table>
<thead>
<tr>
{% for header in table %}
<th>
<div class="text">
{{ header }}
</div>
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in summary %}
<tr class="{% cycle 'row1' 'row2'}">
<td> {{ row.color_pref }} </td>
<td> {{ row.total | intcomma }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
The parent template is also located in the same folder. (project/sales/templates/sales/sale_summary_change_list.html)
{% extends 'admin/change_list.html' %}
{% load humanize %}
{% block content_title %}
<h1> Sales Summary </h1>
{% endblock %}
{% block result_list %}
{% block table %} {% endblock %}
{% endblock %}
{% block pagination %}{% endblock %}
My child template however is not appearing. What am I doing wrong?
You are doing things in wrong way. Just replace {% extends 'sale_summary_change_list.html' %} this block of code with this one {% extends 'sales/sale_summary_change_list.html' %}. It may work for you.

Nested Jinja2 for loops

I'm passing 2 variables (3 including a simple one) to some Jinja from a python script.
On certain runs I want to generate a list with links.
<html>
<body>
<h1>{{ title }}</h1>
<table>
{% if packageURLs is defined %}
{% for x in packageURLs: %}
<a href="{{ x }}">
{% endfor %}
{% for i in packagesList: %}
<tr><td>{{ i }}</td></tr>
{% endfor %}
{" else "}
{% for i in packagesList: %}
<tr><td>{{ i }}</td></tr>
{% endfor %}
{% endif %}
</a>
</table>
</body>
for each 'packageURLs' I want to add a tag then some table tags for 'packages' List. What's happening though is its generating HTML but completing each individual for loop first. So I end up with half a page full of links then another with table rows. How can I have it iterate through both initially?
I found a solution:
<html>
<body>
<h1>{{ title }}</h1>
<table>
{% if packageURLs is defined %}
{% for i,x in packagesList %}
<a href="{{ x }}">
<tr><td>{{ i }}</td></tr>
</a>
{% endfor %}
{" else "}
{% for i in packagesList: %}
<tr><td>{{ i }}</td></tr>
{% endfor %}
{% endif %}
</table>
</body>
Which is populated using zip() in the python script:
f = t.render(title=dataType,packagesList=zip(Info,packageURLs),packageURLs=packageURLs)
I kept the last variable out of laziness as a check since I still want to only execute those different chunks sometimes.

Update table html in django

I am new with Django and I am a little confused trying to update a HTML table populated from the database.
I need to update the table selecting different values from some drop-down list (year, month and provider_type).
This is my table.py:
import django_tables2 as tables
from .models import Proveedor, Estado
class ProveedorTable(tables.Table):
class Meta:
model = Proveedor
fields = ("id_provider", "name", "type", "year", "month")
sequence = ("id_provider", "name", "type", "year", "month")
My views.py
from django.shortcuts import render, render_to_response, RequestContext, HttpResponseRedirect
from django_tables2 import RequestConfig
from .tables import ProveedorTable
from .forms import ProvForm
from .forms import EstadoForm
from .models import Proveedor
from django.contrib import messages
def home(request):
table = ProveedorTable(Proveedor.objects.all())
RequestConfig(request).configure(table)
return render(request,'index.html',{'table': table})
My template index.html
{% load querystring from django_tables2 %}
{% load trans blocktrans from i18n %}
{% load bootstrap_toolkit %}
{% if table.page %}
<div class="table-container">
{% endif %}
{% block table %}
<table class="table table-striped table-condensed table-bordered"{% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
{% block table.thead %}
<thead>
<tr>
{% for column in table.columns %}
{% if column.orderable %}
<th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
{% else %}
<th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
{% endif %}
{% endfor %}
</tr>
</thead>
{% endblock table.thead %}
{% block table.tbody %}
<tbody>
{% for row in table.page.object_list|default:table.rows %} {# support pagination #}
{% block table.tbody.row %}
<tr class="{% cycle "odd" "even" %}">
{% for column, cell in row.items %}
<td {{ column.attrs.td.as_html }}>{{ cell }}</td>
{% endfor %}
</tr>
{% endblock table.tbody.row %}
{% empty %}
{% if table.empty_text %}
{% block table.tbody.empty_text %}
<tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
{% endblock table.tbody.empty_text %}
{% endif %}
{% endfor %}
</tbody>
{% endblock table.tbody %}
{% block table.tfoot %}
<tfoot></tfoot>
{% endblock table.tfoot %}
</table>
{% endblock table %}
{% if table.page %}
{% block pagination %}
<ul class="pagination">
{{ table.page|pagination }}
</ul>
{% endblock pagination %}
{% endif %}
I am confused if I need to use choicefield or an ajax function.
someone can bring me some snippet or a link where I can have a more clear process to implement this functionality
Thanks in advance
Here, <td {{ column.attrs.td.as_html }}>{{ cell }}</td> is where data is being used for displaying data. If you want to do a ajax request here, you have to do it in cell section. For example:
{% for column, cell in row.items %}
{% if column|stringformat:"s" == "some-string" %}
<td {{ column.attrs.td.as_html }} class="ajax-request">{{ cell }}</td>
<!-- or you can use:
<td {{ column.attrs.td.as_html }}><input class="ajax-request" value={{ cell }} type="button (or any other type)"></td>
for choice field, you need to render like
<td {{ column.attrs.td.as_html }}><select id=".ajax-request">
{% for items in cell.values %}
<option value={{ items }}></option>
</select></td>
-->
{% else %}
<td {{ column.attrs.td.as_html }} class="ajax-request">{{ cell }}</td>
{% endif %}
{% endfor %}
<script>
$(document).ready(function(){
$('.ajax-request').change(function(){
var e = document.getElementById("select_dropdown");
var value = e.options[e.selectedIndex].value;
$.ajax({
url: "your-url",
type: "post", // or "get"
data: value,
success: function(data) {
alert(data.result);
}});
});
</script>

Get nth iteration in Django template

I am trying to get the first or nth iteration only in a Django template.
Usually I can iterate through using,
{% for item in pModel %}
{{ item.post }}
{% endfor %}
I need the first iteration but would also like to know how to get the n-th iteration,
{{ pModel.0.post }}` displays nothing and gives no error.
I don't want to iterate through every object in pModel.
I have tried all combinations i.e.
{{ pModel[0][post] }}
{{ pModel.0.[post] }}
{{ pModel[0].post }}
{{ pModel[0][post] }}
{{ pModel.[0][post] }}
{{ pModel.[0].[post] }} etc.
The pModel comes from this view,
def profile(request, id):
pk = id
name = User.objects.all().filter(id=pk)
pModel = reversed(PostModel.objects.all().filter(author = name[0]))
# user_instance = User.objects.all().filter(username = request.user)
return render(request, 'profile.html', {'pModel': pModel, 'current_time': timezone.now()})
The following display nothing,
<strong>{{ pModel.first.post }}</strong>
In the same template I use the pModel which displays correctly so i know that the pModel is working. The complete template,
{% extends 'index.html' %} {% block homepage %}
<div class="post">
{% if pModel %}
<h3>Profile for <strong>{{ pModel.first.post }}</strong></h3>
<p>Last logged in: {{user.last_login|timesince:current_time}} ago on {{ user.last_login }}</p>
<p>Joined {{user.date_joined|timesince:current_time}} ago on {{ user.date_joined }}</p>
{% endif %}
{% if pModel %}
<div class="table-responsive">
<table class='table table-striped table-hover'>
<thead>
<tr>
<th>{{user.username}}'s posts</th>
<th>Topic</th>
<th>Topic Started By</th>
<th>Last Active</th>
<th class="table-cell-center">Views</th>
</tr>
</thead>
<tbody>
{% for item in pModel %}
<tr>
<td>{{ item.post }} uuu {{ pModel.0}}</td>
<td>{{ item.topic.topic }}</td>
<!-- item.topicid.authorid_id -->
<td>{{ item.topic.topicAuthor }}</td>
<td class="icon-nowrap">{{ item.pub_date|timesince:current_time}}</td>
<td class="table-cell-center">{{ item.topic.views }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
{% endblock %}
Your pModel variable is not a queryset or a list, but a reverse iterator. You cannot access individual elements of an iterator, you can only iterate over the iterator once, exhausting it in the process.
To support access of individual elements, you need to convert pModel to a sequence, such as a list:
pModel = list(reversed(PostModel.objects.filter(author = name[0])))
You can then access the index in your template:
{{ pModel.0.post }}
You can use the forloop.counter0 template variable. For example, to access the n'th element:
{% for item in pModel %}
{% if forloop.counter0 == n %}
{{ item.post }}
{% endif %}
{% endfor %}
You can also use first as a special case:
{{ item.first.post }}

Categories

Resources