Breaking or stopping a forloop.counter in django - python

I applied a forloop.counter to label each object numerically in a for loop But I want it to number only the first fifty(50) objects and ignore the rest. Here is my code
{% load thumbnail %}
{% for image in most_viewed %}
<div class="image">
<a href="{{ image.get_absolute_url }}">
{% thumbnail image.image "200x200" crop="10%" as im %}
<span class="forloop">**{{ forloop.counter }}**</span>
<img src="{{ im.url }}">
{% endthumbnail %}
</div>
{% endfor %}
Basically, objects 51 and above should be without numbers

You can try using slice to rewrite the for loop as
{% for image in most_viewed|slice:":50" %}
It will do the iteration for first 50 image in most_viewed.
Edit - Just saw your edit. You can try using the conditional statement forloop.counter <= 50
{% for image in most_viewed %}
<div class="image">
...
{% if forloop.counter <= 50 %}
<span class="forloop">**{{ forloop.counter }}**</span>
{% endif %}
...
</div>
{% endfor %}

Related

Is it possible to custom django-tables2 template for a specific page in this case?

I'm using django-tables2 to render my data in tables in the template..
everything is rendered fine with pagination..
The Designer of our company wants to change the Display of data into blocks instead of simple table. the following picture may explain more.
I Want to ask if I can use Django tables2 in this case ..since I don't want to loose the pagination
Is it possible to custom the django_tables2/table.html file to only fit this case (because I'm using django-tables2 in many other pages in the project)?
Any other ideas may be helpful.
Thanks in advance :)
Yes, you can create a custom template (based on django_tables2/table.html) and set a specific table's template Meta attribute to its path:
import django_tables2 as tables
class Table(tables.Table):
# columns
class Meta:
template = 'table-blocks.html'
or use the template argument to the Table constructor:
table = Table(queryset, template='table-blocks.html')
or use the second argument of the {% render_table %} templatetag:
{% load django_tables2 %}
{% render_table queryset 'table-blocks.html' %}
I was having the same requirement and i had been able to do it. To achieve the desired results i have used bootstrap4 and modified the "django_tables2/bootstrap4.html" template. My modified template only displays blocks which can further be enhanced by embedding more css in it.
{% load django_tables2 %}
{% load i18n %}
{% block table-wrapper %}
<div class="container-fluid relative animatedParent animateOnce p-0" >
{% block table %}
{% block table.tbody %}
<div class="row no-gutters">
<div class="col-md-12">
<div class="pl-3 pr-3 my-3">
<div class="row">
{% for row in table.paginated_rows %}
{% block table.tbody.row %}
<div class="col-md-6 col-lg-3 my-3">
<div class="card r-0 no-b shadow2">
{% for column, cell in row.items %}
<div class="d-flex align-items-center justify-content-between">
<div class="card-body text-center p-5">
{% if column.localize == None %}{{ cell }}{% else %}{% if column.localize %}{{ cell|localize }}{% else %}{{ cell|unlocalize }}{% endif %}{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
{% 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 %}
</div></div></div> </div>
{% endblock table.tbody %}
{% block table.tfoot %}
{% if table.has_footer %}
<tfoot {{ table.attrs.tfoot.as_html }}>
<tr>
{% for column in table.columns %}
<td {{ column.attrs.tf.as_html }}>{{ column.footer }}</td>
{% endfor %}
</tr>
</tfoot>
{% endif %}
{% endblock table.tfoot %}
{% endblock table %}
</div>
{% block pagination %}
{% if table.page and table.paginator.num_pages > 1 %}
<nav aria-label="Table navigation">
<ul class="pagination justify-content-center">
{% if table.page.has_previous %}
{% block pagination.previous %}
<li class="previous page-item">
<a href="{% querystring table.prefixed_page_field=table.page.previous_page_number %}" class="page-link">
<span aria-hidden="true">«</span>
{% trans 'previous' %}
</a>
</li>
{% endblock pagination.previous %}
{% endif %}
{% if table.page.has_previous or table.page.has_next %}
{% block pagination.range %}
{% for p in table.page|table_page_range:table.paginator %}
<li class="page-item{% if table.page.number == p %} active{% endif %}">
<a class="page-link" {% if p != '...' %}href="{% querystring table.prefixed_page_field=p %}"{% endif %}>
{{ p }}
</a>
</li>
{% endfor %}
{% endblock pagination.range %}
{% endif %}
{% if table.page.has_next %}
{% block pagination.next %}
<li class="next page-item">
<a href="{% querystring table.prefixed_page_field=table.page.next_page_number %}" class="page-link">
{% trans 'next' %}
<span aria-hidden="true">»</span>
</a>
</li>
{% endblock pagination.next %}
{% endif %}
</ul>
</nav>
{% endif %}
{% endblock pagination %}
{% endblock table-wrapper %}

Group images by six Django templates

I'm trying to make the forloop group the images into <li> of 6 plus a last li with remainder if the total number isn't a multiple of 6. Right now it doesn't do this correctly some of the tags aren't inside the li.
{% for movie in movies %}
{% if forloop.counter|divisibleby:6 %}
<li>
{% endif %}
{% if forloop.first %}
<li>
{% endif %}
<a href="{{ movie.get_absolute_url }}">
{% thumbnail movie.picture "158x215" as im %}
<img src="{{ im.url }}" alt="">
{% endthumbnail %}
<p>{{ movie.name }}</p>
</a>
{% if forloop.counter|divisibleby:6 %}
</li>
{% endif %}
{% ifequal forloop.counter 5 %}
<li>
{% endifequal %}
{% endfor %}
You can do something like this to create a new <li> element after every 6 iterations.
<li>
{% for movie in movies %}
<a href="{{ movie.get_absolute_url }}">
{% thumbnail movie.picture "158x215" as im %}
<img src="{{ im.url }}" alt="">
{% endthumbnail %}
<p>{{ movie.name }}</p>
</a>
{% if forloop.counter|divisibleby:6 %}
</li>
<li>
{% endif %}
{%endfor%}
</li>

How to ignore the first item in a list in a FOR function?

I have the following for loop that spits out all photos in a list:
{% if photos %}
{% for photo in photos %}
{% thumbnail photo.photo "100x100" crop="center" as im %}
<img src="{{ im.url }}" alt="User's photos" data-ajax="{% url 'photo_increase_view' pk=photo.id %}"/>
{% endthumbnail %}
{% endfor %}
{% endif %}
How can edit this to ignore the first result in the list (i.e. display items 2, 3, 4... etc)
Use slice
Replace
{% for photo in photos %}
by
{% for photo in photos|slice:"1:" %}
So , complete code
{% if photos %}
{% for photo in photos|slice:"1:" %}
{% thumbnail photo.photo "100x100" crop="center" as im %}
<img src="{{ im.url }}" alt="User's photos" data-ajax="{% url 'photo_increase_view' pk=photo.id %}"/>
{% endthumbnail %}
{% endfor %}
{% endif %}
Check out forloop.first using Django; for example:
{% if photos %}
{% for photo in photos %}
{% if not forloop.first %}
{% thumbnail photo.photo "100x100" crop="center" as im %}
<img src="{{ im.url }}" alt="User's photos" data-ajax="{% url 'photo_increase_view' pk=photo.id %}"/>
{% endthumbnail %}
{% endif %}
{% endfor %}
{% endif %}
I guess the answer it's a bit late. But a solution is:
{% for photo in photos[1:] %}
.....
{% endfor %}

Python / Django - have a certain number of items in a loop wrapped in a div

I have a simple for loop in Django, outputting a series of teaser stories. Each is wrapped in a div with a class of row. I have an varibale called num_of_rows, that adds a class of hidden after 2 loops, which hides these divs from view with css.
Here's my code:
{% block content %}
<h1>{{ section.title }}</h1>
{% for story in story_list %}
<div class="row {% if num_of_rows > 2 %} hidden{% endif %}">
<h2>
<a href="{{ story.get_absolute_url }}">
{{ story.headline|upper }}
</a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
</div>
{% endfor %}
{% endblock %}
What I'd like to do is, instead of adding a class of hidden to each individual row, wrap all of the items after 2 items in a separate div and then hide with CSS from that, using Django. This way I can create a much smoother slide-down effect with jQuery.
You can use the forloop variables for this:
{% for story in story_list %}
{% if forloop.counter == 3 %}<div class="hidden">{% endif %}
<div class="row">
<h2>
<a href="{{ story.get_absolute_url }}">
{{ story.headline|upper }}
</a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
</div>
{% if forloop.counter > 2 and forloop.last %}</div>{% endif %}
{% endfor %}

Django {% if forloop.first %} question

I have the following code in my template:
{% for object in object_list %}
{% with game=object.game %}
{% for category in object.game.objectmeta.categories.all %}
{% if category.name|title == 'Puzzle' %}
{% if forloop.first %}
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% endif %}
<div class='game_link' id='dark_gamelink'>
<a class='img_link' href="{% url game_view game.id game.title|slugify %}">
<img class='game_img' src='{{game|thumb:"78x65"}}' alt='{{game.title}}' />
</a>
<div class='top_game_title' style='padding:0'>
<a style='position:relative; top:-3px' id='yellowlink' href="{% url game_view game.id game.title|slugify %}">{{game.title}} -- {{category.name|title}}</a>
<img style='position:relative; top:1px; margin-left:12px' src='thumbsup.gif' width='17' height='18'/>
<span style='position:relative; top:-3px; font-size:10px; color:white'>99%</span>
</div>
{% if game.description|length > 65 %}
{{ game.description|slice:"65" }}...
{% else %}
{{ game.description }}
{% endif %}
</div>
{% if forloop.counter0 == 3 %}
<div class='more_games'><br/></div><div class='side_header' id='dark_gamelink_side'><a class='adventureheader' href=adventure.htm></a></div>
{% endif %}
{% endif %}
{%endfor%}
{% endwith %}
{% endfor %}
Now I'm using this:
{% if forloop.first %}
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% endif %}
to try to detect if this is the first iteration of the for loop immediately preceding it not the parent forloop. In other words I'm trying to detect if it's the 1st iteration of this for loop:
{% for category in object.game.objectmeta.categories.all %}
not this one:
{% for object in object_list %}
The way it is now isn't working because it's displaying this:
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
Twice. How to detect the first iteration of the nested forloop?
Edited:
I have never used these variables but I think forloop.parentloop.first should do it. If not blame me to have misunderstand the Django docs. ;-)
You should check if you are within the parentloop and and then within the first nested node. Please try this modified template. It should you give the right direction.
{% if forloop.parentloop.first %}
I am in the first loop of the parent
{% else %}
{% if forloop.first %}
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% endif %}
{% endif %}
I think the best way to solve this isn't to detect if this is the first iteration in the loop, but rather to write your HTML so that is outside the loop entirely.
You should only be writing HTML elements in the for loop that you actually want repeated for each iteration. If that doesn't work, rethink how you're providing the data to your view (object_list, game, category, etc) so that you can write your markup more easily.
The beginning of your view will probably look something like this:
<div class='side_header' id='dark_gamelink_side'>
<a class='actionheader' href=""></a>
</div>
{% for object in object_list %}
{% with game=object.game %}
{% for category in object.game.objectmeta.categories.all %}
{% if category.name|title == 'Puzzle' %}

Categories