Django: динамически установить SITE_ID в settings.py на основе URL?

Что такое хороший способ динамически установить SIDE_ID в settings.py на основе доменного имени в URL?

У меня есть приложение, которое будет работать со слишком большим количеством доменных имен (в зависимости от города), что пользовательский файл settings.py для каждого домена просто невозможно.

Есть ли способ установить его динамически?

3 ответа

Решение

Вы можете создать собственное промежуточное ПО, которое читает запрос и устанавливает SITE_ID. Я использую этот код на одном из моих сайтов:

class SiteMiddleware(object):
    def process_request(self, request):
        try:
            current_site = Site.objects.get(domain=request.get_host())
        except Site.DoesNotExist:
            current_site = Site.objects.get(id=settings.DEFAULT_SITE_ID)

        request.current_site = current_site
        settings.SITE_ID = current_site.id

Вам следует ознакомиться с документацией Django по промежуточному программному обеспечению, чтобы узнать, как добавить собственное промежуточное программное обеспечение. https://docs.djangoproject.com/en/dev/topics/http/middleware/

Форма кода промежуточного программного обеспечения, похоже, изменилась. Текущая (Django v3.1) форма кода (кажется, работает):

from django.conf import settings
from django.contrib.sites.models import Site

class DynamicSiteDomainMiddleware:

    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):
        try:
            current_site = Site.objects.get(domain=request.get_host())
        except Site.DoesNotExist:
            current_site = Site.objects.get(id=settings.DEFAULT_SITE_ID)

        request.current_site = current_site
        settings.SITE_ID = current_site.id


        response = self.get_response(request)
        return response

Это должно работать для Django v3.2.

Этот код не сильно отличается от предыдущих ответов, поэтому я не буду объяснять, как это работает. Однако я считаю, что написание специального промежуточного программного обеспечения немного изменилось в версии 3.2. Ключевое отличие - это создание подкласса от MiddleWareMixin. Я помещаю этот код в middleware.py и добавляю его в список MIDDLEWARE в settings.py. Второе изменение по сравнению с приведенными выше ответами - это использование SITE_ID непосредственно из settings.py вместо DEFAULT_SITE_ID, поскольку я не вижу смысла устанавливать оба этих параметра в settings.py.

      # middleware.py
class DynamicSiteMiddleware(MiddlewareMixin):
    """
    Make all domain names available through request.site
    """
    def process_request(self, request):
        try:
            current_site = Site.objects.get(domain=request.get_host())
        except Site.DoesNotExist:
            current_site = Site.objects.get(id=settings.SITE_ID)
        request.site = current_site
        settings.SITE_ID = current_site.id
        response = self.get_response(request)
        return response
# settings.py
MIDDLEWARE = [
   ...
   'library.middleware.DynamicSiteMiddleware',
]
Другие вопросы по тегам