nested loop with differents data - list

I have two lists:
campaigns = [{"name":"test", "client": "test_client", "reporter": "myself", "price": 45}...]
filters = ["name", "client", "reporter"]
I want my table to just display the data contained in the filter.
<tbody>
{% for campaign in campaigns %}
<tr role="row" class="odd">
{% for filter in filters%}
<td>{{campaign.filter}}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
Those are 2 differents lists, but I want to use the filters list to get the keys in the campaigns list, I tried multiple writing but it didn't work:
{{campaign[filter]}}
{{campaign}}.{{filter}}
Do you have any idea ?
Thank you.

<tbody>
{% for campaign in campaigns %}
<tr role="row" class="odd">
{% for key, item in campaign.items%}
{% for filter in filters %}
{% if key == filter %}
<td>{{item}}</td>
{% endif %}
{% endfor %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
With this code I was able to retrieve my data in a nested loop. In case this might help someone.

Related

Get all objects' django guardian permissions of the authenticated user in template

I have an application where I am using django-guardian for object-level permission. In my ListView, I am listing all my instances in a table. In each row, I need to show the edit button if the user has the permission to edit this object.
So, I doing something like:
{% extends "base.html" %}
{% load guardian_tags %}
{% block content %}
<table>
<thead>...</thead>
<tbody>
{% for i in items %}
<tr>
<td>{{ i.name }}</td>
<td>
{% get_obj_perms request.user for i as "i_perms" %} <!-- this one -->
{% if "change_item" in i_perms %}
Edit
{% endif %}
</td>
</tr>
{% endif %}
</tbody>
</table>
{% endblock %}
Problem
Doing it that way is not optimized solution from database-wise. This solution makes a database query for each object to get the user permissions. How can I do so but with a single hit to the database to get all the objects' user permissions?
I think you would need to use get_objects_for_user in your view and pass it in to your template via context, eg, in a function based view or as part of your get_extra_context() in a CBV
from guardian.shortcuts import get_objects_for_user
items = Item.objects.all()
permitted_items = get_objects_for_user(request.user, 'change_item', klass=items)
context['permitted_items'] = permitted_items
...
then in your template
{% for i in items %}
<tr>
<td>{{ i.name }}</td>
<td>
{% if i in permitted_items %}
Edit
{% endif %}
</td>
</tr>
{% endfor %}

overriding Django change_list_results

I am customizing my admin panel a little and want to add an additional column to it, so as per the docs I have to override the change_form_results.html file but how do I do it? all I see is this code in it
<tbody>
{% for result in results %}
{% if result.form and result.form.non_field_errors %}
<tr><td colspan="{{ result|length }}">{{ result.form.non_field_errors }}</td> </tr>
{% endif %}
<tr>{% for item in result %}
{{ item }}
{% endfor %}</tr>
{% endfor %}
</tbody>
what change am i suppose to make to above code

Django template integer value iteration

I have the following model
class Table(models.Model):
# Some not important attrs
rows = IntegerField(etc)
cols = IntegerField(etc)
Then I have my view where I'm rendering objects of this model. And I need to build some HTML tables based on the quantity of each objects' rows and cols.
View:
get_tables(request):
tables = Table.objects.all()
return render(request, 'tables.html', {'tables': tables})
I'm trying to do something like:
{% for table in tables %}
<table>
<thead>
<tr>
{% for col in table.cols %}
<th>column label here</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in table.rows %}
<tr>my row</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
I know it is possible to loop for key in dict. But the values cols and rows are integers. How can I achieve this on a Django template?
Try
{% for table in tables %}
<table>
<thead>
<tr>
{% with ''|center:table.cols as range %}
{% for _ in range %}
<th>column label here</th>
{% endfor %}
{% endwith %}
</tr>
</thead>
<tbody>
{% with ''|center:table.rows as range %}
{% for _ in range %}
<tr>my row</tr>
{% endfor %}
{% endwith %}
</tbody>
</table>
{% endfor %}
# You can take use of filter tags in django template
# For Example
Step 1:- Create 'templatetags' package in your app folder.
Step 2:- Create filter.py in 'templatetags' package
Step 3:-
from django import template
register = template.Library()
def table_rows(value):
value_list = [value]
html_row = ''
for val in value_list:
html_row += '<tr></tr>'
return html_row
def table_cols(value):
value_list = [value]
html_cols = ''
for val in value_list:
html_cols += '<td>Hello</td>'
return html_cols
register.filter('table_rows', table_rows)
register.filter('table_cols', table_cols)
Step 4:-
# Your template can be:-
{% load filter %}
{% for table in tables %}
<table border="1">
{% autoescape off %}
{{table.rows|table_rows}}
{{table.cols|table_cols}}
{% endautoescape %}
</table>
{% endfor %}
# You can make changes according to your requirement

django template view nested list

i made a nested list and from that id like to make a table in my template
list looks something like
ground_skills_available = [[category1, [skill1, skill2, skill3]], [category1, [skill1, skill2]]]
Now i want to list it that you got category with below the items, next category and other items. Problem is, i have no clue about hot to show only category, instead of category +all items, since you cant seem to use the index of a list?
Can someone please help me out?
<table>
{% for categories in ground_skills_available %}
{% for category in categories %}
<tr>
<td>{{ category }}</td>
</tr>
{% for skill in category %}
<tr>
<td>{{ skill.name }}</td>
</tr>
{% endfor %}
{% endfor %}
{% endfor %}
Change your outer loop to
{% for category, skills in ground_skills_available %}
This technique is described in the Django for loop docs.
On the first iteration of the loop, this will take the list [category1, [skill1, skill2, skill3], and assign
category = category1
skills = [skill1, skill2, skill3]
You can then display {{ category }}, and loop through skills.
Putting that together, you have:
<table>
{% for category, skills in ground_skills_available %}
<tr>
<td>{{ category }}</td>
</tr>
{% for skill in skills %}
<tr>
<td>{{ skill.name }}</td>
</tr>
{% endfor %}
{% endfor %}
</table>
{% if forloop.index == 1 %} ... some code ... {% endif %}
or
{% if forloop.index0 == 0 %} ... some code ... {% endif %}
Expectation:
{% for categories in ground_skills_available %}
{% for category in categories %}
{% if forloop.first %}
<tr>
<td>{{ category }}</td>
</tr>
{% else %}
{% for skill in category %}
<tr>
<td>{{ skill.name }}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}

How can I check the size of a collection within a Django template?

I have a list in my Django template. I want to do something only if the size of the list is greater than zero.
I have tried myList|length and myList|length_is but they have not been successful.
I've searched all over and don't see any examples. How can I check this?
See https://docs.djangoproject.com/en/stable/ref/templates/builtins/#if : just use, to reproduce their example:
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% else %}
No athletes.
{% endif %}
If you're using a recent Django, changelist 9530 introduced an {% empty %} block, allowing you to write
{% for athlete in athlete_list %}
...
{% empty %}
No athletes
{% endfor %}
Useful when the something that you want to do involves special treatment for lists that might be empty.
A list is considered to be False if it has no elements, so you can do something like this:
{% if mylist %}
<p>I have a list!</p>
{% else %}
<p>I don't have a list!</p>
{% endif %}
If you tried myList|length and myList|length_is and its not getting desired results, then you should use myList.count
You can try with:
{% if theList.object_list.count > 0 %}
blah, blah...
{% else %}
blah, blah....
{% endif %}
This works:
{% if myList|length %}
Do something!
{% endif %}
Why there's so many answers here and why there's so much confusion is that this didn't always work. I think at one point template filters couldn't be used on arguments to the if statement and this was later added. It's also now possible to do things such as {% if myList|length >= 3 %}. The filter should do the equivalent of len(myList) so any type of object that can handle that would also be able to handle the |length filter.
Collection.count no bracket
{% if request.user.is_authenticated %}
{{wishlists.count}}
{% else %}0{% endif %}
I need the collection length to decide whether I should render table <thead></thead>
but don't know why #Django 2.1.7 the chosen answer will fail(empty) my forloop afterward.
I got to use {% if forloop.first %} {% endif %} to overcome:
<table>
{% for record in service_list %}
{% if forloop.first %}
<thead>
<tr>
<th>日期</th>
</tr>
</thead>
{% endif %}
<tbody>
<tr>
<td>{{ record.date }}</td>
</tr>
{% endfor %}
</tbody>
</table>