Simple pagination of Django class-based listview failing, template caching to blame?
Question: In a web-based social Django app I have, there's a feature that allows users
to see all unique users who had a session in the past 5 mins. For this, I'm
using [django user_sessions](https://pypi.python.org/pypi/django-user-
sessions), a plugin that

> makes session objects a first class citizen like other ORM objects.

These recent users are displayed as a list on a template. Each name generated
is clickable on this template - clicking it takes the clicker to the clickee's
profile page. To accomplish that, I've simply wrapped each username in this
tag: `<a href="{% url 'profile' slug=unique_session.user.username
%}#section0"></a>`. This template is **cached** , via using the template tags:
`{%load cache %}{%% cache 30 template_fragment_2 %}{% endcache %}`

Furthermore, the list of recent online users is paginated by 75 (accomplished
via adding `paginate_by = 75` in the `listview` that generates the said list).

Here is the problem: the list of recent users loads up fine in the template
(and clicked usernames lead to correct profiles), but once a user presses
"next page" (_i.e. there were more than 75 people to show_), I get the error:
**django.core.urlresolvers:NoReverseMatch: Reverse for 'profile' with
arguments '()' and keyword arguments '{u'slug': ''}' not found.** After a lot
of debugging, I still have no idea why this is happening. Is it because of
`cache` and `pagination`? Help!

* * *

The view that generates the list is as follows:

    
    
    from user_sessions.models import Session
    
    class OnlineView(ListView):
        model = Session
        template_name = "online.html"
        paginate_by = 75
    
        def get_queryset(self):
            unique_user_sessions = Session.objects.filter(last_activity__gte=(timezone.now()-timedelta(minutes=5))).only('user').distinct('user')
            return unique_user_sessions
    

And the code in the template is:

    
    
    {% extends "base.html" %}
    {% block content %}
        {% load cache %}
        {% cache 30 template_fragment2 %}
        <div class="margin">
            <ol>
                {% for unique_session in object_list %}
                    <li>
                        <a href="{% url 'profile' slug=unique_session.user.username %}#section0">
                            {% if unique_session.user.userprofile.avatar %}
                                <img src="{{ unique_session.user.userprofile.avatar.url }}" alt="no pic" height="20" width="20"></img>
                            {% else %}
                                <img src="{{ STATIC_URL }}img/default-avatar.jpg" alt="no pic" height="20" width="20"></img>
                            {% endif %}
                            {{ unique_session.user.username }}
                        </a>
                    </li>
                {% endfor %}
            </ol>
        </div>
        {% endcache %}
    {% endblock %}
    
    {% block pagination %}
    {% if is_paginated %}
    <div class="pagination">
        {% if page_obj.has_previous %}
        <a href="?page={{ page_obj.previous_page_number }}#section0">back</a>
        {% endif %}
        {% if page_obj.has_next %}
        <a href="?page={{ page_obj.next_page_number }}#section0">forward</a>
        {% endif %}
    </div>
    {% endif %}
    {% endblock %}
    

And here are relevant urlpatterns:

    
    
    url(r'^users/(?P<slug>[\w.@+-]+)/$', UserProfileDetailView.as_view(), name='profile'),
    url(r'^online/$', auth(OnlineView.as_view()), name='online'),
    

* * *

Lastly,

    
    
    Stack trace
    Traceback (most recent call last):
    File "/app/.heroku/python/bin/gunicorn", line 11, in <module>
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 74, in run
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/base.py", line 189, in run
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/base.py", line 72, in run
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/arbiter.py", line 174, in run
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/arbiter.py", line 477, in manage_workers
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/arbiter.py", line 540, in spawn_workers
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/arbiter.py", line 507, in spawn_worker
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/base.py", line 124, in init_process
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 119, in run
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 66, in run_for_one
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 30, in accept
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 130, in handle
    File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 176, in handle_request
    File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/api/web_transaction.py", line 704, in __iter__
    File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/api/web_transaction.py", line 1080, in __call__
    File "/app/.heroku/python/lib/python2.7/site-packages/dj_static.py", line 83, in __call__
    File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/api/web_transaction.py", line 1208, in _nr_wsgi_application_wrapper_
    File "/app/.heroku/python/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 255, in __call__
    File "/app/.heroku/python/lib/python2.7/site-packages/django/core/handlers/base.py", line 140, in get_response
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/response.py", line 105, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/response.py", line 82, in rendered_content
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 140, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/api/function_trace.py", line 98, in dynamic_wrapper
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 830, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 844, in render_node
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/loader_tags.py", line 124, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/api/function_trace.py", line 98, in dynamic_wrapper
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 134, in _render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 830, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 844, in render_node
    File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/hooks/framework_django.py", line 702, in wrapper
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/loader_tags.py", line 63, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 830, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 844, in render_node
    File "/app/.heroku/python/lib/python2.7/site-packages/django/templatetags/cache.py", line 34, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 830, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/base.py", line 844, in render_node
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/defaulttags.py", line 195, in render
    File "/app/.heroku/python/lib/python2.7/site-packages/django/template/defaulttags.py", line 424, in render
    


Answer: The pagination code itself is fine. I think the issue is that some of the
`user` objects that is being returned on the second page of results have an
empty `username`, which is what causes the `NoReverseMatch` error.

The most likely cause of this is that `user` object being returned is an
[anonymous
user](https://docs.djangoproject.com/en/1.8/ref/contrib/auth/#anonymous-users)
\- the `username` is always an empty string in this case.

To verify try modifying your template by wrapping that block in this check:

    
    
    {% if not unique_session.user.is_anonymous %}
        <li>
            <a>...
            </a>
        </li>
    {% endif %}
    

