Django templates: forloop.first and forloop.last - python

I have the following code in my template:
{% for f in friendslist %}
{% if forloop.first %}
// display something
{% endif %}
// display stuff
{% if forloop.last %}
// display something
{% endif %}
{% endfor %}
It works as expected when there is more than one item in the friendslist. But if there is just 1 item, then the content inside the forloop.last
conditional does not display.
I guess this is because the loop in that case is the first, but I mean it's also the last right? So why dosn't both contents inside first and last
conditional show?

In my code they both execute if there is only one element in friendslist. Here is a test you can run in the shell where maybe you can figure out what isn't working:
$ ./manage.py shell
>>> from django import template
>>> t = template.Template("""{% for f in friendslist %}
{% if forloop.first %}
First of the loop
{% endif %}
{{ f }}
{% if forloop.last %}
Last of the loop
{% endif %}
{% endfor %}""")
>>> c = template.Context({'friendslist' : ['one element',]})
>>> t.render(c)
First of the loop
one element
Last of the loop

couldn't you just use an "or" tag like {% if forloop.last or friendlist.count == 1 %}
{% for f in friendslist %}
{% if forloop.first %}
// display something
{% endif %}
// display stuff
{% if forloop.last or friendlist.count == 1 %}
// display something
{% endif %}
{% endfor %}

You can also use ''not'' in template to solve this. It works even there is just an item in the list.
{% for friend in friendslist %}
{% if not forloop.last %}
// display something
{% endif %}
{% if forloop.last %}
// display something
{% endif %}
{% endfor %}

Related

Strting for loop tag inside if else tag raise error

In jinja template there is a for loop in my script, with a start tag {% for each in list_one %} and end tag {% endfor %}.
I want to set 2 conditions for choosing the starting tag of for loop to work. Something like this:
{% if name %}
{% for each in list_one %}
{% else %}
{% for each in list_two %}
{{ each }}
{% endif %}
{% endfor %}
The error I face with is:
jinja2.exceptions.TemplateSyntaxError:Encountered unknown tag 'endif'.
You probably made a nesting mistake. Jinja is expecting this tag, but
currently looking for 'endfor' or 'else'. The innermost block that
needs to be closed is 'for'.
You have to close the for loop before the if clause. In order to decide which list to iterate upon, you can do this instead:
{% if name %}
{% set desired_list = list_one %}
{% else %}
{% set desired_list = list_two %}
{% endif %}
{% for each in desired_list %}
{{ each }}
{% endfor %}
You are trying to use for loop both in if and else blocks. But you missed to close for loop before closing your if and else blocks.
The correct code is like:
{% if name %}
{% for each in list_one %}
{% endfor %}
{% else %}
{% for each in list_two %}
{{ each }}
{% endfor %}
{% endif %}

Django assignment_tag conditional

I'm trying to show partials based on a simple condition. My condition is whether an assignment_tag is True or False.
Templatetag:
from django import template
register = template.Library()
#register.assignment_tag
def partner():
return False
Template:
{% load partner_check %}
{% if partner %}
{% block header %}
{% include 'includes/partner_header.djhtml' %}
{% endblock header %}
{% block footer %}
{% include 'includes/partner_footer.djhtml' %}
{% endblock footer %}
{% endif %}
No matter what I set partner to, the blocks still appear. What am I missing?
Firstly, that's not how assignment tags work. You have never actually called the tag; if partner refers to a (non-existent) template variable named "partner". You call an assignment tag by using it on its own along with a variable to assign it to:
{% partner as partner_value %}
{% if partner_value %}...{% endif %}
Secondly, that's not how blocks work either. You can't dynamically define blocks; they are part of the basic structure of a template, not something that is assigned during evaluation.
I accomplished this by using a context_processor (https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-TEMPLATE_CONTEXT_PROCESSORS)
Context Processor:
def partners(context):
return {
'partner': False
}
Template:
{% block header %}
{% if partner %}
{% include 'includes/partner_header.djhtml' %}
{% else %}
{{ block.super }}
{% endif %}
{% endblock header %}
{% block footer %}
{% if partner %}
{% include 'includes/partner_footer.djhtml' %}
{% else %}
{{ block.super }}
{% endif %}
{% endblock footer %}

Clean up template code

Is there a better way to do the following? Perhaps something like if/elif/else ?
{% if avail.allows_free_streaming %}Free to Stream{% endif %}
{% if avail.requires_paid_subscription %}Subscription{% endif %}
{% if not avail.requires_paid_subscription and not avail.allow_free_streaming %}N/A{% endif %}
Yes, you can use the following approach:
{% if avail.allows_free_streaming %}
Free to Stream
{% elif avail.requires_paid_subscription %}
Subscription
{% else %}
N/A
{% endif %}

Is there a way to use django-inplaceedit to do in-place editing of a column in django-tables2 TemplateColumn?

I tried to make a state_template.html with
{% load inplace_edit %}
{% block extra_header %}
{% inplace_static %}
{% endblock %}
{% inplace_edit "action.action_state" %}
And tables.py has:
action_state = tables.TemplateColumn(template_name='django_tables2/state_template.html', verbose_name="State")
But since action is never being passed to the template, it is giving an error.
Does anyone have any ideas on how to make this work?
This is a very nice question :-)
I think if you update your template (state_template.html), with this should works:
{% load inplace_edit %}
{% block extra_header %}
{% inplace_static %}
{% endblock %}
{% inplace_edit "record.action_state" %}
And this is a recomendation, You should move to the template of the view that renderthe table, but this is only to efficiency:
{% block extra_header %}
{% inplace_static %}
{% endblock %}

How to get only first object in template?

views:
....
d = Data.objects.filter(is_accepted=True)
....
templates:
{% for item in d %}
{% for picture in item.photo_set.all %}
<img class="image" src="{{ picture.photo.url}}">
{% endfor %}
{% endfor %}
How to get only first photo? ({{ picture.photo.url}})
You can index with the dot notation:
{{ item.photo_set.all.0.photo.url }}
You need to use forloop.first. Have a look at the docs.
{% for item in d %}
{% for picture in item.photo_set.all %}
{% if forloop.first %}
<img class="image" src="{{ picture.photo.url}}">
{% endif %}
{% endfor %}
{% endfor %}
First, a sharp knife.
Second, a slice

Categories