Proper way to fill an html array using django/python - arrays

I encounter a small issue about filling my html array in a django template.
I wanted to print one form to one row. Instead of one row to all forms ( that's what i get with the sample code just right there ) :
<thead> <!-- cétait td à la place de th -->
<tr>
{% for entry in headers %}
<th>
{{ entry }}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
<tr>
{%for entry in entries%}
{%for cle, valeur in entry.all_form_entry_json%}
{%for key, valor in headersLoop%}
{%if key == cle%}
<td> {{valeur}}</td>
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
</tr>
</tbody>
The result is such as follow :
You can notice that all the datas are printed to the right corner and go beyond the array limit.
How can i have a result like this ?
Is this possible to do it only with html ? Or should i create a js or css file and import it to this template.html ?
Thank you for your answers !

I think you just wrong place for the html <tr> tag,
the tag <tr> should inside {% for loop..
<thead>
<tr>
{% for entry in headers %}
<th>{{ entry }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for entry in entries %}
<tr>
{% for cle, valeur in entry.all_form_entry_json %}
{% for key, valor in headersLoop %}
{% if key == cle %}
<td>{{ valeur }}</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
{% endfor %}
</tbody>

Related

How to add "caption" tag in TableBlock template in StreamField?

I'd like to add <caption> tag for tables created with TableBlock in StreamField, to make the tables more accessible and semantically correct. Right now, the default template doesn't have that tag. I'm not sure how I should be customizing the table.html template (from the default, and I'm not sure how to render the table if I make a custom class for the table block to add captioning.
<caption> must be <table>'s first child, that's why I need to tinker with the template. Anyone has doe this before?
<table>
<caption>Example Caption</caption> <--- Need this here
<thead>
<th>Header col 1</th>
<th>Header col 2</th>
</thead>
<tbody>
<tr>
<td>Cell col 1</td>
<td>Cell col 2</td>
</tr>
</tbody>
</table>
Take a look at the following code.
TableBlock.py
class TableHead(blocks.StructBlock):
table_head_text = blocks.ListBlock(blocks.CharBlock(max_length=120))
class TableRow(blocks.StructBlock):
table_row_text = blocks.ListBlock(blocks.CharBlock(max_length=120))
class TableBlock(blocks.StructBlock):
caption_text = blocks.CharBlock(max_length=120)
table_head = TableHead()
table_rows = blocks.ListBlock(TableRow())
class Meta:
template = 'wagtail_blocks/table.html'
You will notice that I have set the 'template' property in the 'Meta' class, so you will have to create that file too.
table.html
{% load wagtailcore_tags %}
<table>
<caption>{{ value.caption_text }}</caption>
<thead>
{% for header_text in value.table_head.table_head_text %}
<th>{{ header_text }}</th>
{% endfor %}
</thead>
<tbody>
{% for table_row in value.table_rows %}
<tr>
{% for table_row_text in table_row.table_row_text %}
<td>{{ table_row_text }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
Finally you can easily use your new TableBlock in any page like this
body = StreamField([
('table', TableBlock()),
])

Add link in TableBlock cell

I'm using a TableBlock in a StreamField. Rendering the page, including the table, is fine. But is there anyway to allow the user to enter a link into a table cell? Simply adding a URL has it rendered as text (as I would expect).
Does this require a custom renderer?
Our content team had asked for this feature as well. However, it is not supported in the underlying library that TableBlock uses. We ended up creating a custom StreamField type to display lists of links, rather than trying to kluge links into TableBlock.
I got this problem as well. I know this problem it is been posted a long time ago but I thought to share my solution anyway. I was giving up but then I tried to implement markdown instead as FlipperPA mentioned. And I realised that after installing wagtail-markdown (please follow the instructions), I could tweak my template like this:
<!-- added this at the top of my template -->
{% load wagtailmarkdown %}
....
....
<!-- then in the table replace the word `linebreaksbr` with the word `markdown` -->
<table
class="info-list table table-responsive">
{% if value.table.table_header %}
<thead>
<tr>
{% for column in value.table.table_header %}
{% with forloop.counter0 as col_index %}
<th scope="col" {% cell_classname 0 col_index %}>
{% if column.strip %}
{% if html_renderer %}
{{ column.strip|safe|markdown }} <-- HERE it was {{ column.strip|safe|linebreaksbr }} -->
{% else %}
{{ column.strip|markdown }} <-- HERE it was {{ column.strip|linebreaksbr }} -->
{% endif %}
{% endif %}
</th>
{% endwith %}
{% endfor %}
</tr>
</thead>
{% endif %}
<tbody>
{% for row in value.table.data %}
{% with forloop.counter0 as row_index %}
<tr>
{% for column in row %}
{% with forloop.counter0 as col_index %}
{% if first_col_is_header and forloop.first %}
<th scope="row"
{% cell_classname row_index col_index value.table.table_header %}>
{% if column.strip %}
{% if html_renderer %}
{{ column.strip|safe|markdown }} <-- HERE it was {{ column.strip|safe|linebreaksbr }} -->
{% else %}
{{ column.strip|markdown }} <-- HERE it was {{ column.strip|linebreaksbr }} -->
{% endif %}
{% endif %}
</th>
{% else %}
<td {% cell_classname row_index col_index value.table.table_header %}>
{% if column.strip %}
{% if html_renderer %}
{{ column.strip|safe|markdown }} <-- HERE it was {{ column.strip|safe|linebreaksbr }} -->
{% else %}
{% else %}
{{ column.strip|markdown }} <-- HERE it was {{ column.strip|linebreaksbr }} -->
{% endif %}
{% endif %}
</td>
{% endif %}
{% endwith %}
{% endfor %}
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
And it will render your TableBlock in html. I hope this would help in the future.
Actually, it is pretty easy if you are OK with fact that user has to paste whole HTML of the link, not only href value.
You just need to pass dict with custom rendered option in table_options kwarg of TableBlock. It should look something like this:
TableBlock(table_options={'renderer': 'html'})
Check the docs:
Wagtail and Handsontable
Tested on Wagtail 2.16

How to Display key labels and values in Jekyll for loop data that has been grouped

I got the following to work:
{% assign cars = site.data.inventory %}
{% for item in cars %}
{{item}}
{% endfor %}
The result looks like a jumble of key pairs.
{"brand"=>"Toyota", "model"=>"Celica"}
etc.
All good. Then I threw it a curve ball.
{% assign cars = site.data.inventory | group_by:"model" %}
Now the result looks different, and that makes sense, but it's causing confusion.
{"name"=>"Celica","items"=>[{"brand"=>"Toyota", "model"=>"Celica"}], "size"=>1}
Where this becomes a challenge:
I want to iterate through the "items" in the 2nd result, pulling only the key labels. If I remove the grouping, I can do this:
{% for e in cars %}
{% if forloop.first == true %}
{% for item in e %}
{{item[0]}}
{% endfor %}
{% endif %}
{% for item in e %}
{{item[1]}}
{% endfor %}
{% endfor %}
Works like a charm. The first result is the label, the remaining results show the data. A simple way to make a column header.
However, if I add the group_by in the assign, my {{item[0]}} becomes "name", "items", "size", instead of "brand", "model" where items becomes the entire list {{item}} from the first example.
How do I iterate through the values in bold?
[{"brand"=>"Toyota", "model"=>"Celica"}] while they are grouped?
I think that's what you're trying to do :
{% assign models = site.data.inventory | group_by:"model" %}
<table>
{% for model in models %}
{% if forloop.first == true %}
<tr>
{% for item in model.items.first %}
<th>{{ item[0] }}</th>
{% endfor %}
</tr>
{% endif %}
{% for car in model.items %}
<tr>
{% for field in car %}
<td>{{ field[1] }}</td>
{% endfor %}
</tr>
{% endfor %}
{% endfor %}
</table>

Jekyll and Liquid - Filling table rows with array

I'm having some trouble filling table rows with an array.
What I would like to achieve:
The header row and the first column work fine, but I don't get the numbers right, that the first row contains ONLY the first number of the array (i.e. 50), the second row only the second number from the array etc.
My code:
---
exercises: [Burpees, Squats, Pull ups, Push ups]
rounds: 5
reps: [50, 40, 30, 20, 10]
---
<table class="responsive-table">
<thead>
<tr>
<th scope="col">Round</th>
{% if page.exercises %}
{% for exercise in page.exercises %}
<th scope="col">{{ exercise }}</th>
{% endfor %}
{% endif %}
</tr>
</thead>
<tbody>
{% for n in (1..{{page.rounds}}) %}
<tr>
<th scope="row">Round {{ n }}</th>
<!-- THIS PART DOESNT WORK
{% for exercise in page.exercises %}
<td data-title="{{ exercise }}"> {{ page.reps }} </td>
{% endfor %}
-->
</tr>
{% endfor %}
</tbody>
</table>
How can I fill the cells the way in the picture?
exercises: [Burpees, Squats, Pull ups, Push ups]
reps: [50, 40, 30, 20, 10]
---
<table class="responsive-table table">
<thead>
<tr>
<th scope="col">Round</th>
{% for exercise in page.exercises %}
<th scope="col">{{ exercise }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% assign total = 0 %}
{% for rep in page.reps %}
{% assign total = total | plus: rep %}
<tr>
<th scope="row">Round {{ forloop.index }}</th>
{% for exercise in page.exercises %}
<td data-title="{{ exercise }}"> {{ rep }} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th scope="row">Sum</th>
{% for exercise in page.exercises %}
<td>{{ total }}</td>
{% endfor %}
</tr>
</tfoot>
</table>

Iterate over object in Jinja2?

I'm using Jinja2 on Google App Engine. I have a ListView which renders a generic template. At the moment, I'm not sure exactly what I want to display, so I just want to display each attribute of the model.
Is there a way to iterate over the object to output each one in a table cell?
For example:
{% for record in records %}
<tr>
{% for attribute in record %}
<td>{{ attribute }}</td>
{% endfor %}
</tr>
{% endfor %}
Any advice appreciated.
Thanks
Set getattr in context is a bad idea (and there is already the built-in filter attr). Jinja2 provides dict like access to properties.
I guess you should do:
{% for record in records %}
<tr>
{% for attribute in record.properties() %}
<td>{{ record[attribute] }}</td>
{% endfor %}
</tr>
{% endfor %}
This is better...
This will do the trick in simple python code:
for attribute in record.properties():
print '%s: %s' % (attribute, getattr(record, attribute))
You can put the getattr function in the context so you can call it in jinja2 as shown below:
{% for record in records %}
<tr>
{% for attribute in record.properties() %}
<td>{{ getattr(record, attribute) }}</td>
{% endfor %}
</tr>
{% endfor %}

Resources