4

I trying to use Django Cache to make better my views. Works great, 400ms to 8ms is perfect. But when user access page for the first time, Django cache page with user info in header and when I try log out, page continue with user info.

I try use cache in template too, but isn't good, my problem come from view, so continue 400ms.

My settings.py

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}

My view.py

@cache_page(60 * 15)
def list(request, tag_slug=None):
    page = request.GET.get('page')
    data = questions_controller.list_questions(request, tag_slug, None, page)
    if data:
        return render(request, 'questions/list.html', data)
    return page_not_found(request, "Page not found")
GIA
  • 1,400
  • 2
  • 21
  • 38

2 Answers2

5

I faced the same problem with per-view caching. User info of the first cached user shows for all users. And I can't use Template caching as it is slow.

Best approach is to cache the final result of the view using low-level cache API. If the data is dynamic then use django-signals to clear the stale cached data. Tweak the below code to your requirement.

Views:

from django.core.cache import cache    
def sample(request):
        cached_data = cache.get_many(['query1', 'query2'])
        if cached_data:
            return render(request, 'sample.html', {'query1': cached_data['query1'], 'query2': cached_data['query2']})
        else:
            queryset1 = Model.objects.all()
            queryset2 = Model2.objects.all()
            cache.set_many({'query1': queryset1 , 'query2': queryset2 }, None)
            return render(request, 'sample.html', {'query1': queryset1 , 'query2': queryset2})

Models:

from django.db.models.signals import post_save
from django.core.cache import cache

@receiver(post_save, sender=Model1)
@receiver(post_save, sender=Model2)
def purge_cache(instance, **kwargs):
    cache.delete_many(['query1', 'query2'])

Hope this helps.

PVSK
  • 126
  • 1
  • 8
1

Per-view caching will cache the entire view, so it's a good fit for something like a contact page, but it isn't a good fit for views that have dynamic content.

It sounds like template caching is what you'll need here. For parts of the template that can change, you can add an argument to the {% cache %} tag to uniquely identify it (from the Django docs):

{% load cache %}
{% cache 500 header request.user.username %}
    .. header for logged in user ..
{% endcache %}

Everything in the {% cache %} tag will now be cached per-user so you don't end up with a situation where one user is seeing another user's header.

Franey
  • 4,164
  • 2
  • 16
  • 18
  • but my problem come from view. Continue with 400ms using template cache. – GIA Sep 15 '17 at 16:18
  • 1
    @GuilhermeIA The comment from Tirzono suggests pulling in the user information via AJAX so it doesn't get cached with the rest of the view. If template caching isn't sufficient, that sounds like your best bet. – Franey Sep 15 '17 at 20:19