Django会自动缓存模板吗?

4 投票
3 回答
3689 浏览
提问于 2025-04-15 16:04

我刚接触Django,正在尝试实现一个在两张图片之间投票的系统。不过,似乎页面出现了缓存的问题,因为每次刷新时,有些数值都不对。我在设置里没有配置任何缓存。

这是我的视图代码:

def rate(request, type):
    photos = Photo.objects.order_by('?')[:2]
    c = Context({"photos": photos, "type": type})
    return render_to_response("base_rate.html", c)

还有模板代码:

{% extends "base.html" %}

{% block body %}
<div class="photo">
    <img src="{{photos.0.photo.url}}" alt="Photo" />
    <a href="/rate/vote/{{photos.0.id}}/{{photos.1.id}}" class="vote">Vote</a>
    <a href="/rate/flag/{{photos.0.id}}" class="flag">Flag</a>
</div>

<div class="photo">
    <img src="{{photos.1.photo.url}}" alt="Photo" />
    <a href="/rate/vote/{{photos.1.id}}/{{photos.0.id}}" class="vote">Vote</a>
    <a href="/rate/flag/{{photos.1.id}}" class="flag">Flag</a>
</div>
{% endblock %}

有些页面显示的对象信息是错误的。这里有一个我遇到的例子:

<div class="photo">
    <img src="/img/rate/16photo1.jpg" alt="Photo" />
    <a href="/rate/vote/16/17" class="vote">Vote</a>
    <a href="/rate/flag/16" class="flag">Flag</a>
</div>
<div class="photo">
    <img src="/img/rate/17photo2.jpg" alt="Photo" />
    <a href="/rate/vote/16/16" class="vote">Vote</a>
    <a href="/rate/flag/16" class="flag">Flag</a>
</div>

第二个投票链接应该是“/rate/vote/17/16”,而标记链接应该是“/rate/flag/17”,但出现了问题,我得到了不一致的数据。

有什么想法吗?

3 个回答

1

order_by('?') 的意思是列表是以 随机 的顺序排列的,所以每次你加载页面时,{{ photos.0 }} 的内容都会不同。

另外:

<a href="/rate/vote/{{photos.1.id}}/{{photos.0.id}}" class="vote">Vote</a>
                            ^^^             ^^^

看起来这可能不太对。

1

Django默认情况下不会缓存这些东西。你要确保你的浏览器、网络服务提供商等没有在缓存这些内容。

看起来你的数据库查询没有返回你期待的结果。你可以通过调试工具直接检查,或者如果需要的话,用打印语句来调试。

话说回来,你真的需要认真考虑一下你的应用设计。用GET请求来对应用进行状态改变是个非常糟糕的主意,尤其是你现在的做法。你需要把那些链接改成POST请求,使用一个统一的表单。否则,你会发现一些随机的网络爬虫会破坏你的应用。

8

看看我代码中的这个部分,我在模板里写了这些:

{{ mytable.0.pk }}
{{ mytable.1.pk }}
{{ mytable.0.pk }}
{{ mytable.3.pk }}

然后我得到了这个输出:

91596
54774
156800
23593

这有点奇怪,直到你考虑到 Django 在执行数据库查询时是非常懒惰的。这是我在 MySQL 日志中看到的一次页面加载的记录:

SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1
SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1 OFFSET 1
SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1
SELECT `mytable`.`id` FROM `mytable` ORDER BY RAND() LIMIT 1 OFFSET 3

每次你使用点符号的时候,它都会执行一个全新的查询。我建议你把代码改成这样:

def rate(request, type):
    photos = list(Photo.objects.order_by('?')[:2])
    c = Context({"photos": photos, "type": type})
    return render_to_response("base_rate.html", c)

因为 list() 强制进行了评估,所以它会立即执行查询。此外,这两个项目的数据已经被缓存了,所以没有必要再去数据库查询一次。这样就没问题了。

撰写回答