Using keys with spaces - python

Is there a way to do something like the following in Django templates?
{% for hop in hops%}
<tr>
<td>{{ hop.name }}</td>
<td>{{ hop.mass }}</td>
<td>{{ hop."boil time" }}</td>
</tr>
{% endfor %}
The hop."boil time" doesn't work. The simple solution is rename the key boil_time, but I'm interested in alternatives.

The best way to get at it is to sneak the property name into another variable, like so:
{% for key, value in hop.items %}
{% ifequal key 'boil time' %}
{{ value }}
{% endifequal %}
{% endfor %}
In Django 0.96 (the version used by Google AppEngine) the templating language doesn't support tuple expansion, so it's a bit uglier:
{% for hop in hops %}
<tr>
<td>{{ hop.name }}</td>
<td>{{ hop.mass }}</td>
<td>
{% for item in hop.items %}
{% ifequal item.0 'boil time' %}
{{ item.1 }}
{% endifequal %}
{% endfor %}
</td>
</tr>
{% endfor %}
So, taking your code, we end up with:
{% for hop in hops %}
<tr>
<td>{{ hop.name }}</td>
<td>{{ hop.mass }}</td>
<td>
{% for key, value in hop.items %}
{% ifequal key 'boil time' %}
{{ value }}
{% endifequal %}
{% endfor %}
</td>
</tr>
{% endfor %}
In Django 0.96 (the version on Google AppEnginge), this becomes:
{% for hop in hops %}
<tr>
<td>{{ hop.name }}</td>
<td>{{ hop.mass }}</td>
<td>
{% for item in hop.items %}
{% ifequal item.0 'boil time' %}
{{ item.1 }}
{% endifequal %}
{% endfor %}
</td>
</tr>
{% endfor %}
There's even a wordier way to get at it, using the regroup tag:
{% regroup hop.items by 'boil time' as bt %}
{% for item in bt %}
{% if forloop.first %}
{% for item2 in item.list %}
{% for item3 in item2 %}
{% if not forloop.first %}
{{ item3 }}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}
{% endfor %}

You could use a get filter from djangosnippets: http://www.djangosnippets.org/snippets/1412/
(Renaming the key is probably better...)

For django 0.96, which is what the Google Appengine uses for templates, the following works:
{% for hop in recipe.get_hops %}
{% for item in hop.items %}
{% ifequal item.0 'boil time' %}
<p>{{ item.1 }}</p>
{% endifequal %}
{% endfor %}
{% endfor %}
item.0 is the key and item.1 is the value. Link.

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

string formatting in Html

I am creating a template in HTML
{% for product in products %}
<tr>
<td>{{ product.id }}</td>
<td>{{ product.product_name }}</td>
{% for i in quantities %}
{% if forloop.counter == forloop.parentloop.counter %}
<td id="q1">{{ i }}</td>
{% endif %}
{% endfor %}
{% endfor %}
How can I assign a different id to each item in quantities?
Can I use .format just like we do in python?
Like this?
{% for i in quantities %}
<td id="q{{ forloop.counter }}">{{ i }}</td>
{% endfor %}

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>

Color coding cells in a table based on the cell value using Jinja templates

I have a simple flask app and need to display a table of values, with the cell backgrounds colour coded based on the cell value according to thresholds. I'm generating the table content as follows:
{% block dashboard_table2 %}
<table>
{% for row in data %}
{% for item in row %}
<td>{{ item }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endblock %}
I tried wrapping the values in style tags like this in Python but it didn't work:
if int(value) <= 10:
value = '<p style="background-color:Red">' + value + '</p>'
I'm guessing the CSS for the page is overriding the style attribute. I also tried just setting the text color attribute instead of background-color but no dice. Any suggestions on a good way to do this? I'd like to have a concise way to specify threshold values that aren't hard-coded in the templates.
The easiest way would be to put this display logic in your template:
<table>
{% for row in data %}
<tr>
{% for item in row %}
{% if item <= 10 %}
<td class="under-limit">{{ item }}</td>
{% else %}
<td>{{ item }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
Then, in your CSS you can use:
.under-limit { background-color: red; }
<table>
{% for row in row %}
{% if item <= 10 %}
<tr style ="background-color: red">
<td> {{ item }} </td>
</tr>
{% else %}
<tr>
<td> {{ item }} </td>
</tr>
{% endif %}
{% endfor %}
</table>
This works for me.

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