django缓存多域子域(通配符)返回相同的内容

时间:2010-10-20 00:14:08

标签: django caching subdomain

我有一个奇怪的问题 - 我希望有人之前遇到过类似的问题。

我正在尝试将通过通配符连接的不同子域中的内容缓存到我的django应用程序“example.com”。

所以当我到达subdomain1.example.com时。我在视图中运行差异代码而不是excample.com - 简单的中间件就像这里:Django caching for subdomains

当我从不同的域刷新相同的页面时(例如,使用不同的标签浏览器),事情就出错了。结果产生最后刷新页面的输出。这种行为不依赖于IP(如果其他人在进入主页的同时进入其他子域,您将获得该子域内容。)

如果我先等待加载页面,那么我将移动到其他所有正确加载的页面:|

如果我关闭缓存,则问题不存在。

我的软规范:

  • Ubuntu 8.04 LTS
  • Apache + mod-wsgi
    • 线程10进程未定义multiprocess = false
  • Django 1.23
  • 文件缓存后端

中间件:

class Subdomains:
    def process_request(self, request):
        u'''
            przekierowuje na stronę główną, jeżeli subdomena z której weszliśmy nie jest subdomeną miasta znajdującego się w bazie. Oraz ustawia zmienną request.META['city']!
        '''
        city = get_city_from_host(request.get_host())
        request.city=None
        if city:
            try:
                city = City.objects.filter(slug__exact=city)
                request.city=city[0].slug
            except:
                return HttpResponsePermanentRedirect(ROOT_URL)   

查看:

def post_data(request,address,id):
    url_root = settings.ROOT_URL
    city_subdomain = request.city
    if city_subdomain:
        random_posts = Post.objects.filter(city__slug=city_subdomain).order_by('?')
        if random_posts.count() <= 10:
            pass
        else:
            random_posts = random_posts[:10]

        city = City.objects.filter(slug__exact =  city_subdomain)[0]
        try:
            post = Post.objects.get(id = int(id), city__slug__exact=city.slug)
            nearestinposts = post.nearestinpost_set.select_related(depth=2).all()
            return render_to_response('post_data.html', locals())
        except:
            return HttpResponsePermanentRedirect('http://%s.%s/' % (city_subdomain, settings.ROOT_URL))

    return HttpResponsePermanentRedirect('http://%s' % settings.ROOT_URL)

SETTINGS.PY

CACHE_BACKEND = 'file://%s/cache/' % PROJECT_DIR
CACHE_MIDDLEWARE_SECONDS = 6000
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True
MIDDLEWARE_CLASSES = (
    'django.middleware.cache.UpdateCacheMiddleware',
    'middleware.default.Subdomains',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
)

要修改CACHE_KEY我使用hack:Django caching for subdomains

2 个答案:

答案 0 :(得分:1)

经过一番考虑并阅读一些关于缓存的文档后,我转向了更简单的解决方案,它不需要修改django:

  • 添加中间件子域名,如下所示
class Subdomains:
    def process_request(self, request):
        request.META['HTTP_X_SUBDOMAIN'] = request.get_host()


    def process_response(self, request, response):
        response['X-Subdomain'] = request.META['HTTP_X_SUBDOMAIN']
        return response
  • 将中间件添加到settings.py中的中间件类(注意django.contrib.messages.middleware.MessageMiddleware和django.contrib.auth.middleware.AuthenticationMiddleware +会话范围缓存issue
MIDDLEWARE_CLASSES = (
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.gzip.GZipMiddleware',
    'middleware.default.Subdomains',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware', # we need that to make auth middleware not to add Vary: Cookie to each response
    'django.middleware.cache.FetchFromCacheMiddleware',
)
  • 在视图中使用
  

来自django.views.decorators.vary import vary_on_headers

     

@vary_on_headers( 'X-子域')

答案 1 :(得分:0)

我终于找到了解决问题的方法!问题是我安装了两个版本的django(egg + setup.py)。结果我改变了不正确的utils / cache.py _i18n_cache_key_suffix()函数(我将主机添加到cache_key)。

def _i18n_cache_key_suffix(request, cache_key):
    """If enabled, returns the cache key ending with a locale."""
    if settings.USE_I18N:
        # first check if LocaleMiddleware or another middleware added
        # LANGUAGE_CODE to request, then fall back to the active language
        # which in turn can also fall back to settings.LANGUAGE_CODE
        cache_key += '.%s' % getattr(request, 'LANGUAGE_CODE', get_language())
    cache_key += '.%s' % (request.get_host())
    return cache_key

那么,如果你想要子域名缓存,你应该怎么做?

  • 如果您在每个请求(例如Google Analytics)上使用更改Cookie的内容,请启用StripCookies中间件:

    class StripCookies(object):
        STRIP_RE = re.compile(r'\ b(_ [^ =] + =。+?(?:; | $))')

    def process_request(self, request):
        cookie = self.STRIP_RE.sub('', request.META.get('HTTP_COOKIE', ''))
        request.META['HTTP_COOKIE'] = cookie
    
  • 修改/path/to/django/utils/cache.py以及此帖中提到的_i18n_cache_key_suffix()函数