Адаптация MultiHostMiddleware для django 2.1+

У меня есть один проект django с несколькими разными приложениями, которые должны размещаться в разных доменах. Например, назовем их:

Административный сайт, ourdashboard.com

Первый контентный сайт oursite1.com

Второй контентный сайт oursite2.com

Сайт панели мониторинга предназначен только для издателей контента, а сайты контента — для посетителей. Каждый сайт отличается с точки зрения функциональности, содержания и дизайна. Я хочу, чтобы издатели могли публиковать контент на обоих сайтах, поэтому я не хочу создавать разные проекты django. Но жанр контента требует разных площадок для конкретной аудитории.

Я запустил приложение под названием Dashboard. Я хотел бы, чтобы это приложение размещалось в домене 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.

settings.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'

person Ablivion    schedule 05.02.2019    source источник
comment
не могли бы вы поделиться трассировкой стека ошибок, пожалуйста?   -  person ruddra    schedule 05.02.2019
comment
@ruddra конечно, добавлено в качестве обновления внизу моего исходного поста   -  person Ablivion    schedule 05.02.2019


Ответы (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

К вашему сведению, это непроверенный код, но он предотвратит ошибку, с которой вы сталкиваетесь в данный момент.

Обновлять

Вы можете обновить промежуточное ПО django старого стиля до нового стиля в соответствии с этим документация. Я думаю, вы можете попробовать так:

from django.utils.deprecation import MiddlewareMixin

class MultiHostMiddleware(MiddlewareMixin):
    # rest of the code from your question
person ruddra    schedule 05.02.2019
comment
Ну, по крайней мере, я больше не получаю никаких ошибок. Однако меня также не перенаправляют на правильные URL-адреса. До сих пор я тестировал код и для каждого домена, и для каждого запроса. на URL-адрес ROOT_URLCONF по умолчанию. И это та часть, которая сбивает меня с толку в промежуточном программном обеспечении, потому что я думаю, что это ответ вызывает эту ошибку. Однако я не знаю, как правильно проверить содержимое ответа, в отличие от содержимого запросов, которое я могу просто распечатать. - person Ablivion; 05.02.2019
comment
@Ablivion, если честно, я не уверен, как будет работать это промежуточное ПО. Я только что исправил ошибку, с которой вы столкнулись. :) - person ruddra; 06.02.2019
comment
@Ablivion Я думаю, вы можете изучить это: django-tenant-schemas. readthedocs.io/en/latest/use.html - person ruddra; 08.02.2019
comment
К сожалению, похоже, что он ограничен sudomains, нигде в документации не могу найти, как поддерживать два отдельных домена. - person Ablivion; 08.02.2019
comment
Я так не думаю. Я думаю, что он поддерживает несколько доменов. Пожалуйста, проверьте документацию еще раз. Спасибо - person ruddra; 08.02.2019
comment
наконец заработало, django-hosts решил проблему - person Ablivion; 11.02.2019