Django - complex nested list and tuple unpacking - python

This is simplified but it describes fundamentally what I'm trying to do.
In my views.py, I'm building a list of lists. Each list contains a store name, a list of (product, price) tuples, and a list of (employee, age) tuples. Both the tuple lists are of indeterminable length (but are the same length in each respective line). The outer list containing the name and tuple lists is also of indeterminable length.
[[store_name, [(product_1a, price_1a),(product_2a,price_2a),...], [(employee_1a, age_1a), (employee_2a, age_2a),...]]
[another_store_name, [(product_1b, price_1b),(product_2b,price_2b),...], [(employee_1b, age_1b), (employee_2b, age_2a),...]]
... ]
Each line of the above package needs to be unpacked into one row of a table in my template. I'm trying the following code for my template:
{% for name, products, employees in package %}
<tr>
<td>{{ name }}</td>
{% for product, price in products %}
<td>{{ product }}</td> <td>{{ price }}</td>
{% endfor %}
{% for employee, age in employees %}
<td>{{ employee }}</td> <td>{{ age }}</td>
{% endfor %}
</tr>
{% endfor %}
Actually - I've tried about a dozen different solutions and am at my wits end. Any help on how to repackage and unpack successfully in a template to achieve the desired goal would be most appreciated!
P.S. I'm not really working with store_names, products and employees but this seems the simplest way to put it in a post. I understand totally if you question the need to have this sort of data in one table row!

You can access array sequence elements in the template via arr.0, arr.1 etc. See documentation here: https://docs.djangoproject.com/en/1.4/topics/templates/#variables
So try something like this:
{% for item in package %}
<tr>
<td>{{ item.0 }}</td>
{% for product in item.1 %}
<td>{{ product.0 }}</td> <td>{{ product.1 }}</td>
{% endfor %}
{% for employee in item.2 %}
<td>{{ employee.0 }}</td> <td>{{ employee.1 }}</td>
{% endfor %}
</tr>
{% endfor %}

Related

Sorting by length in Jinja

I have table users that contain column username and entries (a one-to-many relationship with table entries). In my HTML file, I want to display the username and the number of entries from the particular user.
It looks like this:
{% for i in users %}
<tr>
<td>{{ i.username }}</td>
<td>{{ i.entries|length }}</td>
</tr>
{% endfor %}
I want to sort the rows from the user who has the biggest number of entries to the least.
I try this but it doesn't work:
{% for i in users|sort(entries|length) %}
How can I achieve this?
You should ideally create your query-set in you view and in your template, you can access it like so
{% for user in users|sort(attribute="length")
<tr>
<td>{{ user.username }}</td>
<td>{{ user.entries|length }}</td>
</tr>
{% endfor %}
Using length attribute on your item, you can do so with sort(attribute='length'). Taken from the Jinja2 sort filter documentation

Django favourite/compare feature

Just wondering if Sessions can be used to create a quick compare view of two products on my Django app. I'm listing items for sale and would like a user to be able to 'like' multiple items then have a new view to compare the selected products. Any thoughts?
Thanks
Sure, just assign the list products to a session variable.
Then assign the products list to the template, which could look something like that:
<table>
<tr>
<td></td>
{% for product in products %}
<th>{{ product.title }}</th>
{% endfor %}
</tr>
<tr>
<th>Feature 1</th>
{% for product in products %}
<td>{{ product.feature1 }}</td>
{% endfor %}
</tr>
<tr>
<th>Feature 2</th>
{% for product in products %}
<td>{{ product.feature2 }}</td>
{% endfor %}
</tr>
</table>

Using multiple for tags in tables with django

I'm fairly new to Django, and am working on a project where I have items appended to multiple lists and would like to display them in a table. I am using the for tag as there is quite a few items in each list. However, when i run my code, the first item on the list repeats over and over, then the second item repeats over and over, and so on. I have a feeling its because i used multiple for tags. Heres my code:
<table>
{% for x in result.netIncomeAr %}
{% for y in result.d2 %}
<tr>
<td>{{ x }}</td>
<td>{{ y }}</td>
</tr>
{% endfor %}
{% endfor %}
</table>
Any ideas where I went wrong? Thanks.
The inner loop should use the outer loop variable:
{% for x in result.netIncomeAr %}
{% for y in x.d2 %}
UPD (after looking at the result variable):
You need to change the result variable passed into the template, use zip() to join two lists:
result = zip(df['Date'], df['Net Income'])
return render_to_response('ui/search.html', {"result": result}, context)
Then, in the template iterate over the result this way:
<table>
{% for x in result %}
<tr>
<td>{{ x.0 }}</td>
<td>{{ x.1 }}</td>
</tr>
{% endfor %}
</table>

Django Multiple Dictionary Parsing

I'm trying to parse the following data structure in my HTML.
{'GROUPS': {'Group1': [{'key1':'value1','key2':'value2'}, {'key1':'value3', 'key2':'value4'}], 'Group2': [{'key1':'value5','key2':'value6'}, {'key1':'value7', 'key2':'value8'}]}}
The parsing code that I have is as follows:
<tbody>
{% for group,data in data|get_value:"GROUPS" %}
<tr>
<td>{{ group }}</td>
{% for v in data.items %}
<tr>
<td>{{ v|get_value:"key1" }}</td>
<td>{{ v|get_value:"key2" }}</td>
</tr>
{% endfor %}
</tr>
{% endfor %}
</tbody>
get_value is the custom filter that I've written which basically takes the key and the data structure, and returns the value back.
But this isn't working. Can anyone help me figure out why? Thanks!
Firstly, for constant keys, you don't need a custom filter, this will work just fine:
{{ v.key1 }}
That said, data['GROUPS'] is a dict, and you want to iterate over its items, like you did with data.
data is a list though and doesn't need that:
<tbody>
{% for group, data in data.GROUPS.items %}
<tr>
<td>{{ group }}</td>
{% for v in data %}
<tr>
<td>{{ v.key1 }}</td>
<td>{{ v.key2 }}</td>
</tr>
{% endfor %}
</tr>
{% endfor %}
</tbody>

How to structure data to easily build HTML tables in Flask

I am trying to create HTML tables from data stored in a table. My data is read from a table and converted into a dict of lists, e.g.:
x = {'date':[u'2012-06-28', u'2012-06-29', u'2012-06-30'], 'users': [405, 368, 119]}
My goal is to create an HTML table with the following structure for an arbitrary list length:
<table>
<thead>
<th>Date</th>
<th>Users</th>
</thead>
<tbody>
<tr>
<td>2012-06-28</td>
<td>405</td>
</tr>
<tr>
<td>2012-06-29</td>
<td>368</td>
</tr>
<tr>
<td>2012-06-30</td>
<td>119</td>
</tr>
</tbody>
</table>
I have tried doing this two incorrect ways in my Flask template:
<tbody>
{% for line in x %}
<tr>
<td>{{ x.date|tojson|safe }}</td>
<td>{{ x.users }}</td>
</tr>
{% endfor %}
</tbody>
Which prints the entire list into each column.
And:
{% for date in x.date %}
<tr><td>{{ date|tojson|safe }}</td></tr>
{% endfor %}
{% for users in x.users %}
<tr><td>{{ users }}</td></tr>
{% endfor %}
Which simply prints everything into the first column.
These experiments and many other dead ends lead me to believe that there is no simple way to build the table as I would like given my current data structure.
Given this, I have two questions:
1) How would I go about building the table using my current data structure?
2) What is the standard or ideal way to structure data for this use case?
Thanks in advance.
Like you said, you could either change your data structure, or change your template code. Here is one way to keep the current structure:
{% for row_index in range(x['date']|count) %}
<tr>
<td>{{ x[row_index]['date']|tojson|safe }}</td>
<td>{{ x[row_index]['users'] }}</td>
</tr>
{% endfor %}
Or you could restructure your data in python:
x = zip(x['date'], x['users'])
And then use this template:
{% for row in x %}
<tr>
<td>{{ row[0]|tojson|safe }}</td>
<td>{{ row[1] }}</td>
</tr>
{% endfor %}
You can also structure the data so that the template does not depend on the order of the cells:
from itertools import izip
x = [dict(date=d, user=u) for d, u in izip(x['date'], x['users'])]
Then you can access your data like this:
{% for row in x %}
<tr>
<td>{{ row['date']|tojson|safe }}</td>
<td>{{ row['user'] }}</td>
</tr>
{% endfor %}
You might use Flask-Table or for something more complex even leverage Flask-Admin.
Yeah, you really want to use a list of dictionaries instead of a dictionary of lists, that works out better with Jinja2

Categories