python - 为 django 2.1+ 适配 MultiHostMiddleware
问题描述
我有一个 django 项目,其中包含几个不同的应用程序,这些应用程序应该托管在不同的域上。例如,让我们称它们为:
管理网站 ourdashboard.com
第一个内容网站oursite1.com
第二个内容网站oursite2.com
仪表板网站仅适用于内容发布者,而内容网站适用于访问者。每个站点在功能、内容和设计方面都不同。我希望发布者能够在两个站点上发布内容,所以我不会创建不同的 django 项目。但是内容的类型需要针对特定受众的不同站点。
我启动了一个名为仪表板的应用程序。我希望这个应用程序托管在 ourdashboard.com 域上,访问该域将直接访问dashboard.urls
. 所以基本上我想使用单个 django 项目托管多个站点,其中每个域都将链接到特定的应用程序 url 文件。
我做了一些研究,偶然发现了MultiHostMiddleware并尝试实现它。看起来简单易行,但之前从未使用过 djangos 中间件,我一开始就碰壁了。我按照指示正确实施了代码,但我不断收到 500 Internal Server Error。最初我以为我在设置文件中搞砸了一些东西,但看不出问题出在哪里。然后我查看了日志,发现中间件类没有收到get_response
. 中间件文档中的更多研究表明,初始化和可调用函数是必需的,并且__init__
只能接收一个参数“get_response”。此外,我了解到 djangos 中间件在不久前发生了一些重大变化,而 MultiHostMiddleware 的最后一次更新是在 3 年前(目前我使用的是 Django 2.1.5,所以中间件发生了变化)。我一直盯着旧代码 6 小时,寻找可能的解决方案,但老实说,当谈到中间件时,我什至不知道从哪里开始。我什至认为我可以将现有函数用于所需的函数,认为 process_response 是可调用的,因为它返回响应,但我只是掉进了另一个兔子洞。所以,我正在寻找一种方法来适应 django 2.1 的旧代码,以便使用相同的 django 项目托管不同的站点。
设置.py
MIDDLEWARE = [
'network.middleware.MultiHostMiddleware',
...
]
HOST_MIDDLEWARE_URLCONF_MAP = {
"ourdahsboard.com": "dashboard.urls",
"oursite1.com": "musiclounge.urls",
"oursite2.com": "artworld.urls",
}
中间件.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'
解决方案
我认为您正在编写旧式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
仅供参考,它是未经测试的代码,但它可以防止您目前面临的错误。
更新
您可以按照本文档将旧样式 django 中间件更新为新样式。我想你可以这样尝试:
from django.utils.deprecation import MiddlewareMixin
class MultiHostMiddleware(MiddlewareMixin):
# rest of the code from your question
推荐阅读
- sql-server - 当表/视图链接到 Access 时,为什么我不能在 SQL Server 中进行架构更改?
- aws-lambda - AWS lambda 和数据库
- javascript - 是什么阻止了我的代码发现父母的孩子?
- awk - 如何排除打印最后一个字符
- javascript - 像书签中的标签一样打开 url
- django - 设置 ForeignKey 时的 Django 2.1 NOT NULL 约束
- javascript - 键盘导航(上/下)链接问题
- html - 背景边距不为 0
- c - 如何将 tensorflow.crop_and_resize() 用于四边形
- performance - 运算符 && 和 || 的性能