vmm86
@vmm86
Software Developer

Как в одном проекте Django оптимально реализовать сайты на поддоменах в разных городах?

Добрый день!

Планирую использовать Django в предстоящем проекте - несколько десятков Интернет-магазинов в разных городах России. Бэкенд-логика и внешнее оформление для всех сайтов одинаковые, данные - в основном специфичные для каждого города.
В идеале хотелось бы иметь на сервере один Django-проект, в котором можно было бы указать настройки для каждого из сайтов, работающих на отдельных поддоменах.

Предполагаю два возможных варианта архитектуры:
1) Данные каждого сайта хранятся в отдельных базах данных. Подключение к соотв. БД происходит при заходе на соотв. поддомен. Плюсы - разделение бизнес-данных по городам и небольшие объёмы каждой БД. Как в таком случае оптимально организовать логику работы сайтов, храня на сервере один экземпляр проекта Django? Видимо, здесь нужно либо использовать разные DATABASE_ROUTERS, либо в любых CRUD-запросах к моделям явно указывать с помощью using, с какой БД работать, беря её имя(алиас) из поддомена.
2) Данные каждого сайта хранятся в одной базе данных. Очевидный минус в этом случае - в перспективе значительное увеличение объёма одной БД. Насколько я понял, для этого можно использовать Sites Framework, но конкретные шаги в реализации пока непонятны. Как работать с настройками проекта при использовании Sites Framework в одном Django-проекте для всех сайтов? Если нужно создавать несколько файлов settings.py с разными SITE_ID, то как задать логику переключения между ними? И можно ли использовать Sites Framework в первом варианте - используя разные БД?

Кроме того, есть вероятность, что один ли несколько сайтов периодически могут вешать весь сервер, если все сайты будут крутиться на нём одном. Используется глючный сторонний SOAP-сервис, который по крайней мере на старом легаси PHP-бэкенде выдавал такие сюрпризы. Смогу ли я избавиться от этого, написав обёртку для его API на Python - пока непонятно.
Навскидку напрашивается вариант распределять сайты по отдельным виртуальным серверам, но тогда на каждом из них будут отдельные копии проекта, которые нужно будет синхронизировать при изменениях.
Таким образом, выбор стоит не только между использованием одной или множества БД, но и между использованием одного проекта на одном сервере или нескольких инстансов проекта на разных виртуалках.

Если у кого-то есть подобный опыт, лучшие практики и т.п., буду рад услышать ваши мнения.
  • Вопрос задан
  • 1489 просмотров
Пригласить эксперта
Ответы на вопрос 2
@marazmiki
Укротитель питонов
Плюсы первого способа — независимость баз друг от друга, как ни парадоксально. Это значит, что если одна из них ляжет, то остальные могут работать. Или, например, если база для Москвы сильно разрослась, то её можно легко перекинуть на другой сервер. Но в этом случае говорить об одной инстанции Джанго с динамическим переключением роутеров – не лучшая идея. Минусы — геморрой с поддержкой как базы, так и серверов приложений.

Второй способ мне кажется более приемлемым. Основное достоинство в простоте. Положа руку на сердце, мало какой проект выстреливает так, чтобы была реальная необходимость делить его на базы. Вы скорее в теоретический потолок джанги упрётесь. А значительный объём, на который увеличится БД... не надо заниматься преждевременной оптимизацией. Если (ЕСЛИ!) проект выстрелит, то и опыта наберётесь, и мысли дельные появятся, специфические для конкретно этого проекта.

И в данном случае я бы, пожалуй, сделал именно один экземпляр сервера приложений, с одним settings. Чтобы никаких настроек не переключать. Завёл бы модель Domain и миддльварьку, которая брала бы домен из текущего запроса, искала его в этой модели и помещала бы в request (по аналогии с user).

Все настройки можно хранить в БД, используя в качестве признака как раз вышеописанный Domain. Это хорошо ещё и тем, что после изменения настроек не нужно будет перезапускать сервер.

А sites framework – абсолютно бесполезная фигня, его использование оправдано только в одном случае: если используются очень нужные, но уже старые и давно не обновляющиеся батарейки, которые его требовали. Если у вас появилась уникальная возможность начать новый проект без легаси, то очень советую ей воспользоваться. Это непередаваемое ощущение, когда код чистый :)
Ответ написан
neatsoft
@neatsoft
Life is too short for bad software
Отдельные базы данных и DATABASE_ROUTERS это жуткая головная боль - поломанные миграции, неочевидные глюки, существенное замедление разработки, и т.д. Не надо так делать. Есть один подобный проект на сопровождении, поэтому знаю о чем говорю.

При правильно расставленных индексах количество строк в таблице слабо влияет на производительность базы данных (если лимитировать выдачу и задумываться о том какие именно запросы формирует ORM), поэтому о размере бд особо переживать не стоит. Лучше озадачиться грамотным кэшированием.
Чтобы исключить взаимные блокировки при создании новых объектов советую присмотреться к uuid в качестве первичных ключей:
class MyModel(models.Model):
    uuid = models.UUIDField(
        verbose_name=_('Uuid'),
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )

Файл settings.py должен быть только один, особенные настройки для каждого из сайтов нужно хранить в бд. Выбор сайта на основании имени домена можно производить с помощью middleware. Некоторые модели будут общими для всех сайтов, некоторые нужно будет фильтровать.
Если предполагается использование стандартной админки, то для пользователей без superuser статуса нужно будет фильтровать queryset и автоматически добавлять site_id при создании новых объектов.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы