Search code examples
pythondjangocachingdjango-cachedjango-caching

How use Django Cache in view without cache all page


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

Solution

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