2010-01-19 41 views
60

Tôi đang sử dụng phím tắt render_to_response và không muốn tạo đối tượng Phản hồi cụ thể để thêm tiêu đề bổ sung để ngăn bộ đệm ẩn phía máy khách.Chống lại bộ nhớ đệm phía máy khách ở Django

Tôi muốn có một phản ứng có chứa:

  • pragma: no-cache
  • Cache-control: no-cache
  • Cache-control: phải xác nhận lại

Và tất cả các cách tiện lợi khác mà trình duyệt hy vọng sẽ giải thích như là chỉ thị để tránh bộ nhớ đệm.

Có phần mềm trung gian không có bộ nhớ cache hoặc thứ gì đó tương tự có thể thực hiện thủ thuật với sự xâm nhập mã tối thiểu không?

Trả lời

79

Bạn có thể đạt được điều này bằng cách sử dụng trình trang trí cache_control. Ví dụ từ documentation:

from django.views.decorators.cache import never_cache 

@never_cache 
def myview(request): 
    # ... 
+15

Để thực hiện việc này trên tất cả các trình duyệt (đặc biệt FireFox và Opera, nó hoạt động tốt trên trình duyệt IE và Safari/Chrome) tôi cần phải tự thêm 'phản ứng [ "Cache -Kiểm soát "] =" không có bộ nhớ cache, không lưu trữ, phải xác nhận lại "' cùng với '@ never_cache'. '@ never_cache' gọi' add_never_cache_headers() 'và điều này lần lượt gọi' patch_cache_control() 'nhưng điều này chỉ thêm' Cache-Control: max-age = 0', mà dường như không đủ cho các trình duyệt này. Xem http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers – AJJ

+7

Sau khi khám phá mã django nhiều hơn một chút, tôi đã tìm thấy một cách sạch hơn để thêm tiêu đề đó: 'patch_cache_control (phản hồi, no_cache = True, no_store = True, must_revalidate = True)' – AJJ

+6

Ah, đã có một vé mở cho điều này tại code.djangoproject.com: [@never_cache decorator nên thêm 'no-cache '&' must-revalidate '] (https://code.djangoproject.com/ticket/13008) – AJJ

7

Việc viết middleware của riêng tôi là đủ dễ dàng:

from django.http import HttpResponse 


class NoCacheMiddleware(object): 

    def process_response(self, request, response): 

     response['Pragma'] = 'no-cache' 
     response['Cache-Control'] = 'no-cache must-revalidate proxy-revalidate' 

     return response 

Vẫn không thực sự hành xử giống như tôi muốn nhưng cho cũng như thế với @never_cache trang trí

+1

Câu trả lời này cho * Đảm bảo trang web không được lưu trong bộ nhớ cache, trên tất cả các trình duyệt * khá chi tiết: http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached- trên tất cả các trình duyệt – AJJ

42

này phương pháp tiếp cận (sửa đổi nhỏ dung dịch L. De Leo) với phần mềm trung gian tùy chỉnh đã hoạt động tốt đối với tôi như một giải pháp trên toàn trang web:

from django.utils.cache import add_never_cache_headers 

class DisableClientSideCachingMiddleware(object): 
    def process_response(self, request, response): 
     add_never_cache_headers(response) 
     return response 

Điều này làm cho việc sử dụng add_never_cache_headers.


Nếu bạn muốn kết hợp này với UpdateCacheMiddlewareFetchFromCacheMiddleware, để cho phép server-side caching trong khi vô hiệu hóa client-side bộ nhớ đệm, bạn cần phải thêm DisableClientSideCachingMiddleware trước khi mọi thứ khác, như thế này:

MIDDLEWARE_CLASSES = (
    'custom.middleware.DisableClientSideCachingMiddleware', 
    'django.middleware.cache.UpdateCacheMiddleware', 
    # ... all other middleware ... 
    'django.middleware.cache.FetchFromCacheMiddleware', 
) 
+5

+1 để sử dụng 'add_never_cache_headers' thay vì chèn tiêu đề theo cách thủ công. –

+0

Tôi đã đóng gói một cái gì đó dựa trên điều này. Nó bây giờ đã có trên PyPI, và github. https://github.com/incuna/django-never-cache-post – meshy

+0

Chỉ cần một fyi: Điều này không thực sự làm việc cho Opera và page-caching, bởi vì add_never_cache chỉ đặt max-age thành 0, và O, và Opera dường như không tôn vinh tuổi tối đa cho mục đích đó. Xem http://my.opera.com/yngve/blog/2007/02/27/introducing-cache-contexts-or-why-the – AdamC

13

Để bổ sung câu trả lời hiện có. Đây là một trang trí có thêm tiêu đề bổ sung để vô hiệu hóa bộ nhớ đệm:

from django.views.decorators.cache import patch_cache_control 
from functools import wraps 

def never_ever_cache(decorated_function): 
    """Like Django @never_cache but sets more valid cache disabling headers. 

    @never_cache only sets Cache-Control:max-age=0 which is not 
    enough. For example, with max-axe=0 Firefox returns cached results 
    of GET calls when it is restarted. 
    """ 
    @wraps(decorated_function) 
    def wrapper(*args, **kwargs): 
     response = decorated_function(*args, **kwargs) 
     patch_cache_control(
      response, no_cache=True, no_store=True, must_revalidate=True, 
      max_age=0) 
     return response 
    return wrapper 

Và bạn có thể sử dụng nó như:

class SomeView(View): 
    @method_decorator(never_ever_cache) 
    def get(self, request): 
     return HttpResponse('Hello') 
+0

Ai đó có thể giải thích phiếu bầu xuống? Tôi tự hỏi nếu có điều gì đó về cơ bản là sai với mã, bởi vì tôi phụ thuộc vào nó trong một hệ thống sản xuất. –

+0

+1 Hoạt động tốt cho tôi và tôi cũng không thấy bất kỳ vấn đề nào. Để nghe một lý do từ downvoter sẽ được thực sự đánh giá cao. – zerm

5

Về trình duyệt Google Chrome (Version 34.0.1847.116 m) và các trình duyệt khác, Tôi thấy rằng chỉ trang trí @cache_control đang hoạt động. Tôi sử dụng Django 1.6.2.

Sử dụng nó như thế này:

@cache_control(max_age=0, no_cache=True, no_store=True, must_revalidate=True) 
def view(request): 
    ... 
+0

Cách tốt nhất để làm điều này khi ai sử dụng chế độ xem dựa trên lớp học? –

2

Đây là một viết lại của @Meilo's answer cho Django 1.10+:

from django.utils.cache import add_never_cache_headers 

class DisableClientCachingMiddleware(object): 
    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     response = self.get_response(request) 
     add_never_cache_headers(response) 
     return response 
0

tôi đã gãi đầu của tôi khi ba kỳ diệu meta đã không làm việc trong Firefox và Safari.

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> 
<meta http-equiv="Pragma" content="no-cache" /> 
<meta http-equiv="Expires" content="0" /> 

Dường như điều này có thể xảy ra vì một số trình duyệt sẽ bỏ qua phía máy khách meta, vì vậy nó sẽ được xử lý ở phía máy chủ.

Tôi đã thử tất cả các câu trả lời từ bài đăng này cho chế độ xem dựa trên lớp học của tôi (django==1.11.6). Nhưng đề cập đến câu trả lời từ @Lorenzo và @Zags, tôi quyết định viết một phần mềm trung gian mà tôi nghĩ là một phần mềm đơn giản.

Vì vậy, thêm vào câu trả lời tốt khác,

# middleware.py 
class DisableBrowserCacheMiddleware(object): 

    def __init__(self, get_response): 
     self.get_response = get_response 

    def __call__(self, request): 
     response = self.get_response(request) 
     response['Pragma'] = 'no-cache' 
     response['Cache-Control'] = 'no-cache, no-store, must-revalidate' 
     response['Expires'] = '0' 
     return response 

# settings.py 
MIDDLEWARE = [ 
    'myapp.middleware.DisableBrowserCacheMiddleware', 
    ... 
Các vấn đề liên quan