基于 Django 类的列表视图的简单分页失败,归咎于模板缓存?

Posted

技术标签:

【中文标题】基于 Django 类的列表视图的简单分页失败,归咎于模板缓存?【英文标题】:Simple pagination of Django class-based listview failing, template caching to blame? 【发布时间】:2016-02-07 18:46:36 【问题描述】:

在我拥有的基于网络的社交 Django 应用程序中,有一个功能允许用户查看过去 5 分钟内进行过会话的所有唯一用户。为此,我使用了django user_sessions,这是一个插件,

使会话对象像其他 ORM 对象一样成为一等公民。

这些最近的用户在模板上显示为列表。生成的每个名称都可以在此模板上点击 - 点击它会将点击者带到点击者的个人资料页面。为了做到这一点,我简单地将每个用户名包装在这个标签中:<a href="% url 'profile' slug=unique_session.user.username %#section0"></a>。这个模板被缓存,通过使用模板标签:%load cache %%% cache 30 template_fragment_2 %% endcache %

此外,最近在线用户列表按75分页(通过在生成所述列表的listview中添加paginate_by = 75完成)。

问题是:最近用户列表在模板中加载正常(点击用户名会导致正确的个人资料),但是一旦用户按下“下一页”(即有超过 75 人显示),我收到错误:django.core.urlresolvers:NoReverseMatch: Reverse for 'profile' with arguments '()' and keyword arguments 'u'slug': ''' not found . 经过大量调试,我仍然不知道为什么会这样。是因为cachepagination吗?救命!


生成列表的视图如下:

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

而模板中的代码是:

% 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 "   ></img>
                        % else %
                            <img src=" STATIC_URL img/default-avatar.jpg"   ></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 %

这里是相关的 urlpatterns:

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

最后,

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

【问题讨论】:

您能否发布:您的urls.pyNoReverseMatch 错误生成的堆栈跟踪以及您的分页模板代码? @solarissmoke:在模板代码的末尾添加了分页代码,然后是 2 个 urlpatterns(您需要查看整个内容吗?),最后是生成的堆栈跟踪。期待您的来信。 【参考方案1】:

分页代码本身没问题。我认为问题在于结果第二页上返回的某些user 对象有一个空的username,这就是导致NoReverseMatch 错误的原因。

最可能的原因是返回的user 对象是anonymous user - 在这种情况下username 始终是一个空字符串。

要验证尝试通过在此检查中包装该块来修改您的模板:

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

【讨论】:

我会试试这个。与此同时,我正在自己研究这个问题。这是我发现的一些有趣的东西:***.com/questions/21083746/… No is_anonymous 没有解决这个问题,不幸的是,我得到了完全相同的错误! (意味着它在 if 语句中) 虽然,当我迎合用户为“无”时,它起作用了!

以上是关于基于 Django 类的列表视图的简单分页失败,归咎于模板缓存?的主要内容,如果未能解决你的问题,请参考以下文章

Django--基于类的视图的 URL 缓存失败

django.urls.exceptions.NoReverseMatch 基于类的列表视图

Django form.is_valid() 失败的基于类的视图 - Form、SingleObject、DetailMixins

基于 Django 类的视图和通用视图详细信息使用

Django:使用 urls.py 进行分页

如何使用基于 Django 类的通用 ListViews 的分页?