0

I am trying to get the first or nth iteration only in a Django template. Usually I can iterate through using,

{% for item in pModel %}
    {{ item.post }}
{% endfor %}

I need the first iteration but would also like to know how to get the n-th iteration,

{{ pModel.0.post }}` displays nothing and gives no error.

I don't want to iterate through every object in pModel.

I have tried all combinations i.e.

{{ pModel[0][post] }}
{{ pModel.0.[post] }}
{{ pModel[0].post }}
{{ pModel[0][post] }}
{{ pModel.[0][post] }}
{{ pModel.[0].[post] }} etc.

The pModel comes from this view,

def profile(request, id):
    pk = id
    name = User.objects.all().filter(id=pk)
    pModel = reversed(PostModel.objects.all().filter(author = name[0]))
    # user_instance = User.objects.all().filter(username = request.user)
    return render(request, 'profile.html', {'pModel': pModel, 'current_time': timezone.now()})

The following display nothing,

<strong>{{ pModel.first.post }}</strong>

In the same template I use the pModel which displays correctly so i know that the pModel is working. The complete template,

{% extends 'index.html' %} {% block homepage %}
<div class="post">
  {% if pModel %}
    <h3>Profile for <strong>{{ pModel.first.post }}</strong></h3>
  <p>Last logged in: {{user.last_login|timesince:current_time}} ago on {{ user.last_login }}</p>
  <p>Joined {{user.date_joined|timesince:current_time}} ago on {{ user.date_joined }}</p>
  {% endif %}
    {% if pModel %}
    <div class="table-responsive">
      <table class='table table-striped table-hover'>
        <thead>
          <tr>
            <th>{{user.username}}'s posts</th>
            <th>Topic</th>
            <th>Topic Started By</th>
            <th>Last Active</th>
            <th class="table-cell-center">Views</th>
          </tr>
        </thead>
        <tbody>
          {% for item in pModel %}
          <tr>
            <td><a href="{% url 'thread' item.topic_id %}">{{ item.post }} uuu {{ pModel.0}}</a></td>
            <td>{{ item.topic.topic }}</td>
            <!-- item.topicid.authorid_id -->
            <td><a href="{% url 'profile' user.id %}">{{ item.topic.topicAuthor }}</a></td>
            <td class="icon-nowrap">{{ item.pub_date|timesince:current_time}}</td>
            <td class="table-cell-center">{{ item.topic.views }}</td>
          </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
    {% endif %}
</div>
{% endblock %}
Shane G
  • 3,129
  • 10
  • 43
  • 85
  • 2
    What is `pModel`? `.0.` should work for an array.. – Sayse May 17 '16 at 13:24
  • Possible duplicate of [How to access array elements in a Django template?](http://stackoverflow.com/questions/1700661/how-to-access-array-elements-in-a-django-template) – Sayse May 17 '16 at 13:27
  • pModel is created in the view and that has been added to the original question. – Shane G May 17 '16 at 14:01
  • Yes but does it have a `post` field?, does `pModel` return results? does `pModel.0` show anything? Please try to create a [mcve] that demonstrates the problem. – Sayse May 17 '16 at 14:03

2 Answers2

5

You can use the forloop.counter0 template variable. For example, to access the n'th element:

{% for item in pModel %}
    {% if forloop.counter0 == n %}
        {{ item.post }}
    {% endif %}
{% endfor %}

You can also use first as a special case:

{{ item.first.post }}
Selcuk
  • 57,004
  • 12
  • 102
  • 110
  • Yes but this still loops through every iteration. Is it possible to go straight to a particular object in the pModel list? – Shane G May 17 '16 at 13:24
  • @ofey Actually yes, you can for the first instance using `first` (see my updated answer). But for an arbitrary index you have to loop through. – Selcuk May 17 '16 at 13:26
  • Again, it does, I've just found one example in my own code base - `matrix.0.0`, (looking up an array index of an array accessed via an indexer) (Please also don't judge me by our legacy lines of code :P) – Sayse May 17 '16 at 13:46
  • Are you using that directly in the template as a variable like this, {{ matrix.0.0}} ? – Shane G May 17 '16 at 13:50
  • 1
    @Sayse What I tried to say that you can't access to `n'th` element of a sequence if `n` is a context variable itself, as asked in [this question](http://stackoverflow.com/questions/13376576/how-can-i-use-a-variable-as-index-in-django-template) for example. – Selcuk May 17 '16 at 13:50
  • Using first displays nothing for me, {{ pModel.first.post }} – Shane G May 17 '16 at 13:50
  • Ah right ok, yes but that isn't what the OP is trying to do (I think). @ofey - Please see comments under your question. – Sayse May 17 '16 at 13:53
  • 1
    @Sayse Granted, the question is a bit vague but the OP specifically mentions that: `But I need to nth or 0 iteration.` – Selcuk May 17 '16 at 13:55
5

Your pModel variable is not a queryset or a list, but a reverse iterator. You cannot access individual elements of an iterator, you can only iterate over the iterator once, exhausting it in the process.

To support access of individual elements, you need to convert pModel to a sequence, such as a list:

pModel = list(reversed(PostModel.objects.filter(author = name[0])))

You can then access the index in your template:

{{ pModel.0.post }}
knbk
  • 52,111
  • 9
  • 124
  • 122
  • 1
    This is a brilliant answer, thank you. You have no idea how much you have clarified this by saying, "... you can only iterate over the iterator once, exhausting it in the process." Sorry I don't have enough rep to vote this up. Thanks – Shane G May 18 '16 at 09:46