问题
I have recently implemented Django's excellent cache framework. However from what I understand Django will not cache a view that is passed parameters in a get request. I have an Ajax view that is passed get parameters that I would like to cache for X seconds, what would be an easy way to do this?
In psuedo code I currently have a URL:
http://mysites/ajaxthing/?user=foo&items=10
I would like to cache any this url as long as it has the same get parameters.
I'm currently using the cache decorators in my view:
myview(stuff)
myview = cache_page(myview, 60 * 3)
I did read about django's vary headers but it went a little over my head, and I'm not even sure its the correct solution
回答1:
Right, vary headers is not the correct solution, it's used when you want to cache based on client request headers like user-agent etc.
You'll need to use low-level API or template fragment caching. It depends on your views really.
With low-level API it looks something like this:
from django.core.cache import cache
def get_user(request):
user_id = request.GET.get("user_id")
user = cache.get("user_id_%s"%user_id)
if user is None:
user = User.objects.get(pk=user_id)
cache.set("user_id_%s"%user_id, user, 10*60) # 10 minutes
...
..
.
回答2:
Yes, you can use django-view-cache-utils, here is code for your case:
from view_cache_utils import cache_page_with_prefix
from django.utils.hashcompat import md5_constructor
...
@cache_page_with_prefix(60*15, lambda request: md5_constructor(request.get_full_path()).hexdigest())
def my_view(request):
...
回答3:
It appears that you no longer need to do anything more complicated than placing @cache_page([length of time]) above your View function you are trying to cache, irrespective of whether you have parameters in the URL.
For example, if you have a url like:
http://example.com/user/some_user_id
Your view function in views.py would look something like this:
from django.views.decorators.cache import cache_page
...
@cache_page(60 * 10)
def get_user_detail(request, user_id=None):
...
return render(...)
回答4:
This should be no longer an issue in Django 1.3+. See: https://docs.djangoproject.com/en/dev/topics/cache/#using-vary-headers
回答5:
From my reading of the source code and empirical testing, the @cache_page decorator natively handles GET parameters correctly (at least in Django 2.2).
Digging through the source:
- The decorator is defined in django.views.decorators.cache
- It calls
django.utils.decorators.decorator_from_middleware_with_args() - Which calls
django.utils.decorators.make_middleware_decorator() - Which is a silly level of complex. A veritable onion of functions returning functions. The important bit is it calls
middleware.process_request()where 'middleware' isdjango.middleware.cache.CacheMiddleware. - Which calls
django.utils.cache.get_cache_key()to generate the cache key. - Which calls
django.utils.cache._generate_cache_header_key(). - Which calls
request.build_absolute_uri()where 'request' isdjango.http.request.HttpRequest - Which calls
django.http.request.HttpRequest.get_full_path() - Which calls
django.http.request.HttpRequest._get_full_path() - Which, finally, includes
self.META.get('QUERY_STRING', '')in the string it returns.
On the flip side, when the response is complete a similar path goes through middleware.process_response() which eventually calls django.utils.cache._generate_cache_header_key() to determine where to store the response in the cache.
Empirically, I can see that requests to the decorated view are being cached and the response changes when the GET parameters change.
回答6:
a bit late, but you can use django-view-cache-utils for that.
来源:https://stackoverflow.com/questions/1590372/cache-a-django-view-that-has-url-parameters