使MultiHostMiddleware适应Django 2.1+

时间:2019-02-05 07:51:51

标签: python django request response middleware

我有一个django项目,其中包含几个应该在不同域中托管的不同应用程序。例如,我们称它们为:

管理网站ourdashboard.com

第一个内容站点oursite1.com

第二个内容站点oursite2.com

仪表板网站仅适用于内容发布者,而内容网站则适用于访问者。每个站点的功能,内容和设计都不同。我希望发布者能够在两个站点上发布内容,所以我不会创建其他django项目。但是内容的流派需要针对特定​​受众的不同站点。

我启动了一个名为“仪表板”的应用程序。我希望此应用程序托管在ourdashboard.com域上,访问该域将直接访问dashboard.urls。因此,基本上我想使用一个django项目托管多个站点,其中每个域都将链接到特定的应用程序url文件。

我做了一些研究,偶然发现MultiHostMiddleware并试图实现它。看起来很简单,但是以前从未使用过djangos中间件,所以我一开始就碰到了砖墙。我按照说明正确实施了代码,但始终收到500 Internal Server Error。最初我以为我弄乱了设置文件中的内容,但看不到问题出在哪里。然后,我查看了日志,发现中间件类未收到get_responseMiddleware Documentation中的更多研究表明,初始化和可调用函数是必需的,并且__init__只能接收单个参数'get_response'。此外,我了解到不久前djangos中间件发生了一些大变化,而MultiHostMiddleware的最新更新是3年前了(当前我使用的是Django 2.1.5,因此中间件发生了变化)。我一直在盯着旧代码6h,寻找可能的解决方案,但是老实说,我什至不知道从中间件开始。我什至以为我可以将现有功能用于必需的功能,以为process_response是可调用的,因为它返回响应,但是我陷入了另一个困境。因此,我正在寻找一种方法来针对django 2.1修改此旧代码,以便使用相同的django项目托管不同的网站。

settings.py

MIDDLEWARE = [
    'network.middleware.MultiHostMiddleware',
    ...
]

HOST_MIDDLEWARE_URLCONF_MAP = {
    "ourdahsboard.com": "dashboard.urls",
    "oursite1.com": "musiclounge.urls",
    "oursite2.com": "artworld.urls",
}

middleware.py

import time
from django.conf import settings
from django.utils.cache import patch_vary_headers

class MultiHostMiddleware:

    def process_request(self, request):
        try:
            request.META["LoadingStart"] = time.time()
            host = request.META["HTTP_HOST"]
            #if host[-3:] == ":80":
            #    host = host[:-3] # ignore default port number, if present

            # best way to do this.
            host_port = host.split(':')
            if len(host_port)==2:                    
                host = host_port[0] 

            if host in settings.HOST_MIDDLEWARE_URLCONF_MAP:
                request.urlconf = settings.HOST_MIDDLEWARE_URLCONF_MAP[host]
                request.META["MultiHost"] = str(request.urlconf)
            else:
                request.META["MultiHost"] = str(settings.ROOT_URLCONF)

        except KeyError:
            pass # use default urlconf (settings.ROOT_URLCONF)

    def process_response(self, request, response):
        if 'MultiHost' in request.META:
            response['MultiHost'] = request.META.get("MultiHost")

        if 'LoadingStart' in request.META:
            _loading_time = time.time() - int(request.META["LoadingStart"])
            response['LoadingTime'] = "%.2fs" % ( _loading_time, )

        if getattr(request, "urlconf", None):
            patch_vary_headers(response, ('Host',))
        return response

**更新**

As, requestedstack error:

Traceback (most recent call last):
   File "/home/user/webapps/django_network/network/network/wsgi.py", line 16, in <module>
     application = get_wsgi_application()
   File "/home/user/webapps/django_network/lib/python3.7/Django-2.1.5-py3.7.egg/django/core/wsgi.py", line 13, in get_wsgi_application
     return WSGIHandler()
   File "/home/user/webapps/django_network/lib/python3.7/Django-2.1.5-py3.7.egg/django/core/handlers/wsgi.py", line 136, in __init__
     self.load_middleware()
   File "/home/user/webapps/django_network/lib/python3.7/Django-2.1.5-py3.7.egg/django/core/handlers/base.py", line 36, in load_middleware
     mw_instance = middleware(handler)
 TypeError: __init__() missing 1 required positional argument: 'get_response'

1 个答案:

答案 0 :(得分:1)

我认为您正在编写旧样式MIDDLEWARE(在Django 1.10之前一直存在),您需要像这样更新它:

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


    def __call__(self, request):
        loading_time = time.time()
        request.META["LoadingStart"] = loading_time
        host = request.META["HTTP_HOST"]    
        host_port = host.split(':')
        response = self.get_response(request)
        if len(host_port)==2:                    
            host = host_port[0] 
        try:
            if host in settings.HOST_MIDDLEWARE_URLCONF_MAP:
                request.urlconf = settings.HOST_MIDDLEWARE_URLCONF_MAP[host]
                request.META["MultiHost"] = str(request.urlconf)
                response['MultiHost'] = str(request.urlconf)
            else:
                request.META["MultiHost"] = str(settings.ROOT_URLCONF)
                response["MultiHost"] = str(settings.ROOT_URLCONF)

        except KeyError:
            pass 
        _loading_time = time.time() - loading_time
        response['LoadingTime'] = "%.2fs" % ( _loading_time, )
        if getattr(request, "urlconf", None):
            patch_vary_headers(response, ('Host',)) 
        return response

仅供参考,它是未经测试的代码,但可以防止您目前遇到的错误。

更新

您可以按照此documentation将旧样式的django中间件更新为新样式。我认为您可以尝试这样:

from django.utils.deprecation import MiddlewareMixin

class MultiHostMiddleware(MiddlewareMixin):
    # rest of the code from your question