2014-04-28 26 views
2

我在我的Django 1.5.6應用難倒一個緩存的問題:@vary_on_cookie由於失敗非Django的餅乾

@vary_on_cookie 
@cache_page(24 * 60 * 60, key_prefix=':1:community') 
@rendered_with("general/community.html") 
@allow_http("GET") 
def community(request): 
    ... 
    return { ... } 

本地緩存工作正常,但是當我在升級測試,@ vary_on_cookie不工作 - 我可以查詢看到正在執行社區()正在對後續調用此頁面執行。

我在本地環境中使用相同的Redis緩存登臺,以消除差異更新我的設置,但當地的環境繼續正常運行。

望着鍵的Redis在其高速緩存中,我可以看到的問題是什麼 - 分期每到這個頁面被調用時,新的鍵添加到緩存。從cache.keys('*community*')比較輸出:

LOCAL:

先打電話社區頁面:

[u'community:1:views.decorators.cache.cache_page.:1:community.GET.b528759dd79cf1c6b405290c0bc05e39.3b7d4c38ec8d92512a4a0847f4738298.en-us.America/New_York', 
u'community:1:views.decorators.cache.cache_header.:1:community.b528759dd79cf1c6b405290c0bc05e39.en-us.America/New_York'] 

第二個電話(同一用戶):

[u'community:1:views.decorators.cache.cache_page.:1:community.GET.b528759dd79cf1c6b405290c0bc05e39.3b7d4c38ec8d92512a4a0847f4738298.en-us.America/New_York', 
u'community:1:views.decorators.cache.cache_header.:1:community.b528759dd79cf1c6b405290c0bc05e39.en-us.America/New_York'] 

公告有相同數量的在兩種情況下都是關鍵

分期:

先打電話社區頁面:

[u'community:1:views.decorators.cache.cache_header.:1:community.b528759dd79cf1c6b405290c0bc05e39.en-us.America/New_York',  
u'community:1:views.decorators.cache.cache_page.:1:community.GET.b528759dd79cf1c6b405290c0bc05e39.559380b85dc0cdcf0ff25051df78987d.en-us.America/New_York'] 

第二個電話(同一用戶):

[u'community:1:views.decorators.cache.cache_header.:1:community.b528759dd79cf1c6b405290c0bc05e39.en-us.America/New_York', 
u'community:1:views.decorators.cache.cache_page.:1:community.GET.b528759dd79cf1c6b405290c0bc05e39.559380b85dc0cdcf0ff25051df78987d.en-us.America/New_York', 
u'community:1:views.decorators.cache.cache_page.:1:community.GET.b528759dd79cf1c6b405290c0bc05e39.6ec85abcc8a14d66800228bdccc537f0.en-us.America/New_York'] 

注意,一個額外的條目已被添加到緩存中,雖然這是同一個用戶!

我難倒哪裏何去何從。這兩種環境都使用SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'。暫存環境清楚地認識到,這是每個其他方式的相同用戶。在@vary_on_cookie中發生了什麼,它正在創建階段的差異,但不是本地的?

我檢查我所有的升級與地方差異的,仔細檢查我的自定義中間件,但我沒有來看看什麼想法。任何想法,甚至接下來要看什麼都將不勝感激。謝謝!

UPDATE

我檢查django.utils.cache._generate_cache_key()來看看它是如何產生的緩存鍵的那最後的十六進制部分。我天真地以爲它只是看着Django自己的Cookie(如會話ID),但我看到它使用所有傳入HTTP_COOKIE餅乾的 - 這意味着,Django和非Django的。對我而言,這意味着來自Google Analytics和New Relic的Cookie,這兩者都不是我在本地運行的。

for header in headerlist: # headerlist = [u'HTTP_COOKIE'] 
     value = request.META.get(header, None) # the string of all cookies, for ex: __atuvc=39%7C17%2C8%7C18; csrftoken=dPqaXS6XVGp2UUvfhEW9kS6R6WPHQlE4; sessionid=j6a83wbsq1sez9bz75n0tzl4n884umg2' 
     if value is not None: 
      ctx.update(force_bytes(value)) 

這是真的嗎?!所有使用@vary_on_cookie的全球Django網站都受到第三方cookies的阻撓?

回答

0

我創建了一個自定義裝飾器,它可以竊取HTTP頭以隔離用戶的ID。 (儘管它在回覆給瀏覽器的響應中設置了Vary: DJANGO_USERID, Cookie,但它不包含實際的ID。)

我希望對此解決方案提供任何反饋,因爲它超出了我的Django舒適區域。謝謝!

def vary_on_user(view): 
    """                                                  
    Adapted from django.views.decorators.vary_on_cookie                                               
    """ 
    @wraps(view, assigned=available_attrs(view)) 
    def inner_func(request, *args, **kwargs): 
     request.META['HTTP_DJANGO_USERID'] = request.user.id 
     response = view(request, *args, **kwargs) 
     patch_vary_headers(response, ('DJANGO_USERID',)) 
     return response 
    return inner_func