Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Django cache templates automatically?

I'm new to Django and trying to implement a voting system between two images. However, it looks like the page is being cached or something because when I refresh it, some values are wrong. I have no cache setup in my Settings.

Here is the View:

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

and the template:

{% 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 %}

Some pages will contain wrong info for the objects. Here is an example source that I am getting:

<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>

The second Vote href should be "/rate/vote/17/16" and the flag href should be "/rate/flag/17" but something is going wrong and I am getting inconsistent data.

Any ideas?

like image 623
Matt McCormick Avatar asked Dec 29 '22 11:12

Matt McCormick


1 Answers

Taking a look at this in some of my code, I have this in my template:

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

And I get this output:

91596
54774
156800
23593

Odd, until you consider that django executes database queries very lazily. This is what shows up in my mysql log for one page load:

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

Each time you use the dot notation, it is executing an entire new query. I'd suggest modifying your code like so:

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)

Because the list() is forcing an evaluation, it will execute the query right then and there. In addition, the data for both of those items is already cached, so there is no reason to hit the database again. You should be good to go.

like image 112
Jack M. Avatar answered Jan 15 '23 16:01

Jack M.