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',
]