2012-06-07 30 views
7

Tôi đã sử dụng UpdateCacheMiddlewareFetchFromCacheMiddleware MiddleWare để bật bộ nhớ đệm ẩn danh trên toàn trang web với các mức thành công khác nhau.Kỹ thuật cho phân lớp Django UpdateCacheMiddleware và FetchFromCacheMiddleware

Vấn đề lớn nhất là Middleware chỉ lưu trữ yêu cầu đầu tiên của người dùng ẩn danh. Vì cookie session_id được đặt trên phản hồi đầu tiên đó, các yêu cầu tiếp theo của người dùng ẩn danh đó không nhấn bộ nhớ cache do bộ nhớ cache cấp chế độ xem thay đổi trên Tiêu đề.

Các trang web của tôi không có sự khác biệt có ý nghĩa giữa những người dùng ẩn danh và, cho đến khi chúng thay đổi, tôi có thể xử lý điều đó thông qua Ajax. Kết quả là, tôi quyết định cố gắng phân lớp đệm đệm của Bộ đệm đệm của Django để không còn thay đổi trên Tiêu đề. Thay vào đó, nó thay đổi trên Người dùng Ẩn danh và Người dùng đã đăng nhập. Bởi vì tôi đang sử dụng phụ trợ Auth và trình xử lý đó xảy ra trước khi tìm nạp từ bộ nhớ cache, có vẻ như nó hoạt động.

class AnonymousUpdateCacheMiddleware(UpdateCacheMiddleware): 

    def process_response(self, request, response): 
     """ 
     Sets the cache, if needed. 
     We are overriding it in order to change the behavior of learn_cache_key(). 
     """ 

     if not self._should_update_cache(request, response): 
      # We don't need to update the cache, just return. 
      return response 
     if not response.status_code == 200: 
      return response 

     timeout = get_max_age(response) 
     if timeout == None: 
      timeout = self.cache_timeout 
     elif timeout == 0: 
      # max-age was set to 0, don't bother caching. 
      return response 
     patch_response_headers(response, timeout) 
     if timeout: 
      ######### HERE IS WHERE IT REALLY GOES DOWN ####### 
      cache_key = self.learn_cache_key(request, response, self.cache_timeout, self.key_prefix, cache=self.cache) 
      if hasattr(response, 'render') and callable(response.render): 
       response.add_post_render_callback(
        lambda r: self.cache.set(cache_key, r, timeout) 
       ) 
      else: 
       self.cache.set(cache_key, response, timeout) 
     return response 

    def learn_cache_key(self, request, response, timeout, key_prefix, cache=None): 
     """_generate_cache_header_key() creates a key for the given request path, adjusted for locales. 

      With this key, a new cache key is set via _generate_cache_key() for the HttpResponse 

      The subsequent anonymous request to this path hits the FetchFromCacheMiddleware in the 
      request capturing phase, which then looks up the headerlist value cached here on the initial response. 

      FetchFromMiddleWare calcuates a cache_key based on the values of the listed headers using _generate_cache_key 
      and then looks for the response stored under that key. If the headers are the same as those 
      set here, there will be a cache hit and the cached HTTPResponse is returned. 
     """ 

     key_prefix = key_prefix or settings.CACHE_MIDDLEWARE_KEY_PREFIX 
     cache_timeout = self.cache_timeout or settings.CACHE_MIDDLEWARE_SECONDS 
     cache = cache or get_cache(settings.CACHE_MIDDLEWARE_ALIAS) 

     cache_key = _generate_cache_header_key(key_prefix, request) 

     # Django normally varies caching by headers so that authed/anonymous users do not see same pages 
     # This makes Google Analytics cookies break caching; 
     # It also means that different anonymous session_ids break caching, so only first anon request works 
     # In this subclass, we are ignoring headers and instead varying on authed vs. anonymous users 
     # Alternatively, we could also strip cookies potentially for the same outcome 

     # if response.has_header('Vary'): 
     #  headerlist = ['HTTP_' + header.upper().replace('-', '_') 
     #     for header in cc_delim_re.split(response['Vary'])] 
     # else: 
     headerlist = [] 

     cache.set(cache_key, headerlist, cache_timeout) 
     return _generate_cache_key(request, request.method, headerlist, key_prefix) 

Các Trình tải, có trách nhiệm để lấy trang từ bộ nhớ cache, trông như thế này

class AnonymousFetchFromCacheMiddleware(FetchFromCacheMiddleware): 

    def process_request(self, request): 
     """ 
     Checks whether the page is already cached and returns the cached 
     version if available. 
     """ 
     if request.user.is_authenticated(): 
      request._cache_update_cache = False 
      return None 
     else: 
      return super(SmarterFetchFromCacheMiddleware, self).process_request(request) 

Có rất nhiều sao chép cho UpdateCacheMiddleware, rõ ràng. Tôi không thể tìm ra một cái móc tốt hơn để làm sạch hơn.

Thông thường, điều này có vẻ giống như một cách tiếp cận tốt không? Bất kỳ vấn đề rõ ràng mà đến với tâm trí?

Cảm ơn, Bến

Trả lời

2

Bạn có thể làm việc này bằng cách tạm thời loại bỏ không mong muốn khác nhau các lĩnh vực từ response['Vary']:

from django.utils.cache import cc_delim_re 

class AnonymousUpdateCacheMiddleware(UpdateCacheMiddleware): 
    def process_response(self, request, response): 
     vary = None 
     if not request.user.is_authenticated() and response.has_header('Vary'): 
       vary = response['Vary'] 
       # only hide cookie here, add more as your usage 
       response['Vary'] = ', '.join(
        filter(lambda v: v != 'cookie', cc_delim_re.split(vary)) 
     response = super(AnonymousUpdateCacheMiddleware, self).process_response(request, response) 
     if vary is not None: 
      response['Vary'] = vary 
     return response 

Ngoài ra, thiết CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True trong cài đặt để ngăn chặn bộ nhớ cache cho người dùng xác thực.

+0

Xin chào okm, việc triển khai của tôi có hiệu quả, đúng không? – Ben

+0

@Ben Không có sự khác biệt lớn. Nhưng so sánh w/sao chép mã, tôi thích thừa kế ở đây. Đó là rõ ràng hơn, có ít mã trong dự án của bạn và sẽ gây ra ít đau đầu khi bạn nâng cấp phiên bản Django – okm

+0

nhờ okm, tất cả các điểm tốt – Ben

Các vấn đề liên quan