Django - how to tell if a template fragment is alr

2019-04-12 22:33发布

I am using Django's Template Fragment Caching so in a template.html file

{% extends 'base.html' %}
{% load cache %}
{% block content %}
  {% cache 500 "myCacheKey" %}
     My html here...
  {% endcache %}
{% endblock %}

This is working fine - I can see it's getting cached and hit but the view is doing something expensive to provide data to this view and thats getting called every time.

In views.py

def index(request)
   data = api.getSomeExpensiveData()
   return render_to_response('template.html', {'data':data} )

So how do I tell if the cache is avail before the call to api.getSomeExpensiveData()?

I can't use cache.get('myCacheKey') as the cache isn't found - does it use some naming scheme and if so can I either use something like

cache.get(cache.getTemplateFragmentKey("myCacheKey"))

or

cache.getTemplateFragment("myCacheKey")

2条回答
迷人小祖宗
2楼-- · 2019-04-12 22:39

I found this SO - How do I access template cache?

And adapted it to

from django.utils.hashcompat import md5_constructor
from django.utils.http import urlquote
from django.core.cache import cache

def hasFragmentCache(key, variables = []):
    hash = md5_constructor(u':'.join([urlquote(var) for var in variables]))    
    return cache.has_key(cache_key)

Edit - I've accepted skirmantas answer as whilst this does exactly as asked its the better approach as then the template and view are more loosly coupled. Using this method you need to know the name of each cache fragment and whats used where. A designer moves things around and it would fall over.

查看更多
做个烂人
3楼-- · 2019-04-12 22:51

If you do not use that data in your view, something as simple as this might work:

def index(request)
   get_data = api.getSomeExpensiveData
   return render_to_response('template.html', {'get_data':get_data} )

In template

{% block content %}
  {% cache 500 "myCacheKey" %}
     {{ get_data.something }}
     Or maybe
     {% for something in get_data %}
     {% endfor %}
  {% endcache %}
{% endblock %}

Django template automatically calls all callable objects.

EDIT:

If you need to use get_data more than once in your template you'll need some wrapper. Something similar to this:

def index(request)
   class get_data(object):
       data = False
       def __call__(self):
           if not self.data:
               self.data = api.getSomeExpensiveData()
           return self.data
   return render_to_response('template.html', {'get_data':get_data()} )
查看更多
登录 后发表回答