Can I evaluate expressions in a django template? - python

I'm trying to display table rows with alternating colors. For that, I have two css classes row1 and row2 that I'd like to assign in an alternating pattern to the rows of a table. Ideally, I'd determine if the row is odd or even based on the forloop.counter variable
This is what I'd like the template to do (invalid code, but I think it's self explaning).
{% for norma in normas %}
{% if forloop.counter %2 != 0 %}
<tr class="row1">
{% else %}
<tr class="row2">
{% endif %}
<td>yadda... yadda</td>
.
.
.
{% endfor %}
Is there a way to do this within django template system?

Use cycle - the example shows this exact purpose

Just use in your {%for%} loop :
<tr class="{% cycle 'row1' 'row2' %}>
django templete will cycle through each row. you can add as many items in the cycle.

the followin post explains how to get alternating row colors in Django.
Alternate Row Coloring in Django Template with More Than One Set of Rows

Related

Is there a way to have parallel for loops in HTML?

I am using Python FLask to build a webapp and I am trying to push a nested list to a table in HTML.
Python
item = [[22-03-20, $1409.50, 22-03-20], [22-03-20, $60.00, 22-03-20]]
current HTML
{% for rows in item %}
<tr>
<th scope="row">•</th>
{% for cell in rows %}
<td>{{cell}}</td>
{% endfor %}
<td>edit</td>
</tr>
{% endfor %}
The reason for a duplicate of dates in the nested list is because I need to create a special route page to the date itself.
Output I want to achieve
Basically, the edit will redirect to the page to the respective date. As I have multiple expenses of the same date, I can't just use the unique id within the table.
PROBLEM
The current HTML I have is able to output the 3 items I need, date, expense, date but I can't put a URL redirect to the 3rd variable, date. Is there a way to have 2 for loops running parallel to each other, so I could go through 2 lists at the same time? or is there a better way to do what I want to achieve?
Found a way looking through the documentation again, don't need a parallel for loop actually. I changed the nested list to a tuple in a list. Not sure if this is the best way to do it though.
Python
item = [(22-03-20, $1409.50, 22-03-20), (22-03-20, $60.00, 22-03-20)]
HTML
{% for x,y,z in item %}
<tr>
<th scope="row">•</th>
<td>{{x}}</td>
<td>{{y}}</td>
<td>edit</td>
</tr>
{% endfor %}
I think you should use a list of maps.
item = [
{
'date':'22-03-20',
'price':'$1409.50',
'href':'URI'
},
{
'date':'22-03-20',
'price':'$60.00',
'href':'URI'
},
]
so,
{% for row in item %}
<tr>
<th scope="row">•</th>
<td>{{row.date}}</td>
<td>{{row.price}}</td>
<td>
edit
</td>
</tr>
{% endfor %}

How to get out some items from an array

In my flask / jinja2 app, I am getting some rows from a database to print in a table. For each row I want to define an identifier for the row from the first item, define the class of the row with the second item and print the rest of the row as table data. I am doing it like this, it works but feels a bit kludgy:
{%- for item in row %}
{% if loop.index==1 %}
<tr id="rec{{item}}"
{% elif loop.index==2 %}
class="{{item}}" >
{% else %}
<td>{{item}}</td>
{% endif %}
{% endfor -%}</tr>
I would like to do something like:
id="rec"+row.pop()
class=row.pop()
then use the variables id and class to define the row and afterwards iterate through what is left of the list. Is this possible in jinja2?
(Using jinja 2.8 as installed on debian 9, but may of course upgrade if that makes things better)
I think you can use slicing in Jinja templates, could you try this, since I can't test it atm:
<tr id="rec{{row[0]}}"
class="{{row[1]}}" >
{% for item in row[2:] %}
<td>{{item}}</td>
{% endfor -%}
</tr>
You could get the first items from the array using their indices and use a slice (e.g. row[2:]) of the array for the for-loop:
<tr id="rec{{row[0]}}" class="{{row[1]}}" >
{%- for item in row[2:] %}
<td>{{item}}</td>
{% endfor -%}</tr>

Alternate Row Colors in Html Tables Using Django

How does one alternate row colors in a table in django that's generated using a for loop from a list? In asp.net it is possible to do math on the view to easily calculate that, but from what I understand that kind of math is not possible in django, so I'm looking for another way.
I think you are looking for cycle.
{% for o in some_list %}
<tr class="{% cycle 'red' 'green' %}">
...
</tr>
{% endfor %}

django template question (accessing a list)

I am writing a template for my first django website.
I am passing a list of dictionaries to the template in a variable. I also need to pass a few other lists which hold boolean flags. (Note: all lists have the same length)
The template looks something like this:
<html>
<head><title>First page</title></head><body>
{% for item in data_tables %}
<table>
<tbody>
<tr><td colspan="15">
{% if level_one_flags[forloop.counter-1] %}
<tr><td>Premier League
{% endif %}
<tr><td>Junior league
<tr><td>Member count
{% if level_two_flags[forloop.counter-1] %}
<tr><td>Ashtano League
{% endif %}
</tbody>
</table>
{% endfor %}
</body>
</html>
I am getting the following error:
Template error
In template /mytemplate.html, error at
line 7 Could not parse the remainder:
'[forloop.counter-1]' from
'level_one_flags[forloop.counter-1]'
I am, not suprised I am getting this error, since I was just trying to see if would work. So far, from the documentation, I have not found out how to obtain the items in a list by index (i.e. other than by enumeration).
Does anyone know how I may access a list by index in a template?
In short, Django doesn't do what you want.
The for loop has a number of useful properties within a loop.
forloop.counter The current iteration of the loop (1-indexed)
forloop.counter0 The current iteration of the loop (0-indexed)
forloop.revcounter The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0 The number of iterations from the end of the loop (0-indexed)
forloop.first True if this is the first time through the loop
forloop.last True if this is the last time through the loop
forloop.parentloop For nested loops, this is the loop "above" the current one
You could probably use forloop.counter0 to get the zero-based indexes you want; unfortunately, the Django template language doesn't support variable array indexes (You can do {{ foo.5 }}, but you can't do {{ foo.{{bar}} }}).
What I usually do is to try and arrange the data in the view to make it easier to present in the template. As an example, for you could create an array in your view composed of dictionaries so that all you have to do is loop through the array and pull exactly what you need out of the individual dictionaries. For really complicated things, I've gone so far as to create a DataRow object that would correctly format the data for a particular row in a table.
You use the dot-operator to index the array, or, really, to do anything.
Technically, when the template system
encounters a dot, it tries the
following lookups, in this order:
* Dictionary lookup
* Attribute lookup
* Method call
* List-index lookup
I don't believe you can do math on the index. You'll have to pass in your array constructed in some other way so that you don't have to do this subtraction.
Try using "slice" to access a list by index
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#slice
Perhaps a better way is to use forloop.last. Of course, this will require that you send to the template the specific level_one_flag and level_two_flag out of the level_one_flags and level_two_flags arrays, but I think this solution keeps a better logical separation between view and template:
<html>
<head><title>First page</title></head><body>
{% for item in data_tables %}
<table>
<tbody>
<tr><td colspan="15">
{% if forloop.last and level_one_flag %}
<tr><td>Premier League
{% endif %}
<tr><td>Junior league
<tr><td>Member count
{% if forloop.last and level_two_flag %}
<tr><td>Ashtano League
{% endif %}
</tbody>
</table>
{% endfor %}
</body>
</html>

How to display a table of images in Django template system?

I'm developing a Django-based site for fun, and wondered if anyone knows how to solve this problem. I want to display images in a table, like a gallery, inside a template. Does anyone know how to do this? I've tried a multidimensional list, but I am getting nowhere.
I believe question is more CSS related than Django.
Are all your images the same size? If yes, just float all of them and let the bounding div break the images. Your template would looks like something like this (ignore the inline CSS!):
<div style="width:400px">
{% for image in image_list%}
<div style="float:left; width:100px; height:100px;">
{{ image.whatever }}
</div>
{% endfor%}
</div>
This would give you a "table" with 4 columns.
If your images have different widths and heights, I would go with something like display:inline-block, this article explains how it works:
http://robertnyman.com/2010/02/24/css-display-inline-block-why-it-rocks-and-why-it-sucks/
Edit If all you want is to convert a list into a table, I guess you can use this template:
{% for image in image_list %}
{% if forloop.first %}
<tr>
{% endif %}
<td>{{ forloop.counter }} - {{ image }}</td>
{% if forloop.last %}
</tr>
{% else %}
{% if forloop.counter|divisibleby:"4" %}
</tr><tr>
{% endif %}
{% endif %}
{% endfor %}
But this code is not tested! I just wrote it :)
Why don't you use a dictionary? Then you could represent points (0,0), (1,1), (0,1) etc with something like this,
mydict = {0: [0, 1, 2],
1: [0, 1, 2],
2: [0, 1, 2]}
where the elements of the list are your image names.
{0: ["image1.jpg", "image2.jpg", "image3.jpg"] .. }
In this case, mydict[0][0] refers to the first element of the first row, and so on.
--
To access a dict in the template (Django Doc), you could use something like,
# (key would be 0, value would be a list [0,1,2,3..]
{% for key, value in mydict.items %}
{% for img in value %}
<img src="{{img}}">
{% endfor %}
{% endfor %}
Do you really need to use table to align your images the way you need? If you need to get something like this http://blog.mozilla.com/webdev/files/2009/02/gallery-view.jpg, please take a look at inline-block CSS property. It is supported by all major browsers including IE6+ (with a little fix).
http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/
Here's a much much simpler way that what others have answered:
The goal is to create a new row after each 4th image displayed. A 1 dimensional list is all you need.
One option would be to close the after each 4th . You can use the forloop.counter or you can use {% cycle '' '' '' '' %} after you create each tag. Note: I'm speculating a bit about your HTML structure. {% cycle '' '' '' '' %} might do just as fine.
Here is what cycle does: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#cycle
If you're using s floated to the left, use the same cycle but add a line break after each 4th .

Categories