【问题标题】:django caching multi domain subdomain (wildcard) returning same contentdjango缓存多域子域(通配符)返回相同的内容
【发布时间】:2010-10-20 00:14:07
【问题描述】:

我遇到了奇怪的问题 - 我希望以前有人遇到过类似的问题。

我正在尝试缓存来自通过通配符连接到我的 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

【问题讨论】:

  • 您需要显示视图的代码以及如何缓存它。
  • 我猜您正在为所有子域使用单个缓存。在这种情况下,将子域添加为缓存键的前缀。否则不同的子域会覆盖彼此的缓存项。
  • @OmerGertel:我使用了不同的方法来更改 CACHE_KEY - 以 stackoverflow.com/questions/772050/… 结尾。而且我一开始就运行了这个问题:) 现在,当我不同时提出请求时,一切都很好——我得到了不同的内容。我想知道 Apache / mod_wsgi 是否未以某种方式配置以干扰 django 缓存 - 我必须检查标头。
  • @Daniel 我刚刚添加了一些代码 :)
  • 哦,我差点忘了 - 在我的开发服务器上一切正常:|我可以在多个选项卡中多次推送刷新 - 也许是线程/进程问题?我猜DEV服务器是一个进程和线程?

标签: django caching subdomain


【解决方案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 导入 vary_on_headers

@vary_on_headers('X-子域')

【讨论】:

    【解决方案2】:

    我终于找到了解决问题的方法!问题是我安装了两个版本的 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
    

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

    • 如果您在每个请求中使用更改您的 cookie 的东西(例如 Google Analytics),请启用 StripCookies 中间件:

      类 StripCookies(对象):
      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() 函数

    【讨论】:

      猜你喜欢
      • 2020-10-04
      • 1970-01-01
      • 2018-11-30
      • 1970-01-01
      • 1970-01-01
      • 2014-12-29
      • 2020-08-23
      • 2014-08-02
      • 2012-12-16
      相关资源
      最近更新 更多