Django主机名中间件被缓存

时间:2011-08-23 16:40:08

标签: django caching middleware

我创建了一个Django项目来管理两个共享一些后端代码的独立站点。这两个网站都在不同的应用程序中。每个应用都有自己的models.py,views.py,模板等......

为了能够对不同的主机名做出不同的反应,我创建了一个URLconf中间件:

class HostnameBasedUrlconfMiddleware(object):
    """This middleware parses the hostname from the request, and selects the
    urlconf accordingly.

    To set a custom urlconf according to the current hostname, add an URLCONF
    dictionary to your settings.py file.

    URLCONF = {
        'example.com': 'urls_example',
        'example.dev': 'urls_dev',
        'admin.example.dev': 'apps.admin.urls'
    }

    If the hostname is not found in the URLCONF dictionary, the default
    ROOT_URLCONF setting will be used.

    """

    def process_request(self, request):
        # Decide which urlconf to use. Fallback is to use the ROOT_URLCONF
        # as defined in the settings.py file.
        try:
            hostname = request.META['HTTP_HOST']
            request.urlconf = settings.URLCONF[hostname]
        except (KeyError, AttributeError):
            pass

        return None

这似乎最初起作用,但后来我意识到必须进行某种缓存。

启动服务器并请求站点A时,它会显示出来。如果我然后请求站点B,则站点A出现。有时(但并非总是),经过几次重新加载后,站点B最终会显示出来。重新启动服务器并请求站点B后,它将显示,但现在站点A将显示站点B内容。

这发生在内置的devserver和gunicorn上。

我尝试使用curl请求网站以避免浏览器缓存,没有区别。

我还怀疑它可能是某种模板名称冲突,但所有模板都位于各自模板文件夹中唯一命名的子文件夹中。

我没有安装memcached,我没有使用任何缓存中间件。

可能是什么问题?是否有一些内部自动缓存?

1 个答案:

答案 0 :(得分:0)

以下是在urlconf中替换的代码(至少为1.3):

<强> django.core.handlers.base

class BaseHandler(object):

   [...snip...]

   def get_response(self, request):
        "Returns an HttpResponse object for the given HttpRequest"
        from django.core import exceptions, urlresolvers
        from django.conf import settings

        try:
            # Setup default url resolver for this thread, this code is outside
            # the try/except so we don't get a spurious "unbound local
            # variable" exception in the event an exception is raised before
            # resolver is set
            urlconf = settings.ROOT_URLCONF
            urlresolvers.set_urlconf(urlconf)
            resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
            try:
                response = None
                # Apply request middleware
                for middleware_method in self._request_middleware:
                    response = middleware_method(request)
                    if response:
                        break

                if response is None:
                    if hasattr(request, "urlconf"):
                        # Reset url resolver with a custom urlconf.
                        urlconf = request.urlconf
                        urlresolvers.set_urlconf(urlconf)
                        resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
    [...snip...]

所以,看起来它只是直接使用request.urlconf中的值。您的中间件正在直接设置request值。

我安装django-debug-toolbar以确认request.urlconf的值是否a)被设置或b)在此过程中被更改。

为了绝对确定,为什么不暂时将代码更改为:

            request.urlconf = settings.URLCONF[hostname]
            request.urlconf_set = datetime.datetime.now()

然后,您可以查看调试工具栏中的值(或者只是在模板中输出它们)以查看可能发生的情况。

但是,我建议您不要使用中间件,而只需为每个域设置不同的settings.py文件。然后,在您正在使用的任何Web服务器中,将每个服务器设置为使用其自己的.wsgi文件,该文件指向其自己的设置文件,如下所示:

<强> settings_a.py

from settings import *
ROOT_URLCONF = 'urls_a.py'

<强> settings_b.py

from settings import *
ROOT_URLCONF = 'urls_b.py'