Pull to refresh

Comments 13

У меня вопрос: зачем делать полный inspectdb, если для авторизации нужна ровно одна таблица. Думаю стоило бы упомянуть, что inspectdb может принимать 0+ имён таблиц на вход. Так же при тотальном переезде думаю имеет смысл запилить «DB R/W router» с небольшой доп обвязкой на уровне view чтобы чтение и запись производились из/в разные БД. Так и пользователей перенесете, и прочий необходимый контент.
1. спасибо за подсказку про inspectdb, добавил в статью
2. в моем случае чтение и запись (пользователей) как раз в разные БД и просходит.
При авторизации:
— вначале ищем учетную запись в локальной БД Django (django.contrib.auth.backends.ModelBackend)
— если user не найден (еще не скопирован из Joomla)
— ищем и авторизуем в БД Joomla (самописный 'users.backend.JoomlaBackend')
— создаем копию пользователя в БД Django (в JoomlaBackend: `return User.objects.create_user(...)`)
> User тут — это встроенная модель `django.contrib.auth.models.User`

При следующей авторизации пользователь уже есть в локальной БД.
Мне кажется, давать доступ одному приложению к базе данных другого (работающего) приложения − это плохая идея. Я бы в вашей ситуации авторизовал Django-пользователя в Joomla HTTP-запросом, при помощи requests, например.
Плохая затея для сайта авторизовать пользователя на уровне кода.
И read-only доступ к «старой» БД — по факту единственный и что более важно дешёвый вариант при большой миграции проекта. Тут главное доступ на запись отключить иначе фиаско братан )
А на уровне чего еще можно его авторизовать? Базы данных?
я имел ввиду авторизацию вида http запроса к старому сайту
Прошу прощения, что высказался не очень понятно. Разделять базу данных между несколькими приложениями − это всегда плохая идея. Попробую показать, почему.
  1. Технически неоправданные зависимости. Если мы изменяем процедуру логина в одном приложении, нам наверняка нужно дорабатывать аналогичный кусок кода в другом приложении. Если мы апгрейдим СУБД для одного приложения, нам нужно убедиться, что это будет работать в другом приложении. И т. д.
  2. Параллельный доступ. Рано или поздно вы наткнётесь на проблемы с хронологией процессов в обоих приложениях.
  3. Производительность. Чем больше общих ресурсов, тем больше вероятность, что один из них станет бутылочным горлышком.
  4. Возможность апгрейда. Рано или поздно вам станет мало read-only-доступа: появится необходимость синхронизировать данные в профилях пользователей, например.

Что же делать вместо общего доступа к БД? Воспользоваться API для доступа к данным. Есть несколько плагинов для Joomla, которые обеспечивают REST-сервисы. Если не все, то какие-то из них наверняка имеют возможность авторизовать клиента (в нашем случае, Django-приложение).

В крайнем случае, если доработка Joomla совсем никак невозможна, то лучше авторизовывать Django-юзера на лету через джумловскую форму логина (тоже какой-никакой интерфейс).

Это всё очень очевидные архитектурные вопросы, которые давно разжёваны. Вот пару источников, чтобы не быть голословным:

www.ben-morris.com/a-shared-database-is-still-an-anti-pattern-no-matter-what-the-justification
stackoverflow.com/q/3479297/10424832
softwareengineering.stackexchange.com/q/105786
на счёт шарить базу на несколько приложений в rw режиме — согласен, плохая затея (хотя и тут есть место для дискуссии). как я и говорил выше для миграции только read-only доступ к старой бд
Не могу согласится с вами полностью. Это очень неочевидный архитектурный вопрос, и даже в приведенных вами ссылках, мнения разделились, например:
На stackoverflow:
— 14 голосов за раздельные БД
— 28 голосов за shared DB
На stackexchange:
— 39 голосов за DB-per-Application
— 22 голоса за shared DB

Я сам двумя руками за максимальную изоляцию сервисов, и мне хотелось сделать именно так, как вы советуете. Но в данном случае я решил использовать Read-only доступ к старой БД по нескольким причинам:
1. новый сервис не подразумевает регистрации новых пользователей, только использование старых
2. из этой же БД мне нужны другие данные, которых на данных момент 120Гб, они нужны часто и за большие периоды времени (по паре сотен Мб за раз), но тоже в Read-Only режиме. Использовать тут REST сервис значит создать бутылочное горлышко на пустом месте, а копировать read-only данные в новую БД не вижу смысла.
3. я не знаю PHP в общем и Joomla в частности, и не уверен в своих возможностях прикрутить туда REST сервис и обеспечить его безопасность.
4. (касательно только пользователей) я не нашел бесплатного oAuth2 модуля к Joomla с хорошей документацией, а без документации см. п. 3

Кстати говоря, я до сих пор не уверен, что принял правильное решение, и как сильно нужно разделять или наоборот интегрировать эти два сервиса.

Поэтому Magican Tanner, тут действительно есть место для дискуссии, и спасибо вам за участие в ней.
а не подскажете что за dbrouter такой — manager.router.DatabaseAppsRouter?
о! Большое спасибо за замечание. Когда я писал статью, на этапе обобщения и выкидывания проекто-специфических кусков кода, я взял настройку DATABASE_ROUTERS из ответа на Stackoverflow, будучи в святой уверенности, что «manager.router.DatabaseAppsRouter» это встроенный в Django роутер. Это оказалось неверным и уже путь импорта, начинающийся не с «django» должен был меня насторожить.

Сейчас исправлю статью.

В таком случае, если вы не против моей "саморекламы", в этой ветке оставлю ссылку на свое простенькое решение для подобного случая: https://pypi.org/project/django-dbrouter/


было написано мною пару лет назад для решения той же задачи, и совсем недавно я его таки-решил нормально оформить в виде пакета.
заодно интересно было-бы получить обратную связь — все ли понятно? удобно ли использовать? как вам мой английский?


PS
тем более, ваш вариант не обрабатывает такие важные методы, как allow_relation и allow_migrate
Таким образом, при manage.py makemigrations выможете получить попытку писать в эту БД (и хорошо, если она доступна лишь на чтение)

Модуль как модуль, описание понятное, код очевидный. Если будет развиватся — добавьте тестов по вкусу.
Мне было проще скопировать десяток строчек из документации, чем тащить дополнительную зависимость, но если баз данных много, то такой модуль пригодится.

P.S. Методы allow_relation и allow_migrate не так уж важны:
1. Насколько я знаю, Django до сих пор не поддерживает отношения (foreign key) между разными БД, так что `allow_relation` это просто задел на будущее Django
2. `allow_migrate` это тоже перестраховка в Django. Этот метод не препятствует `makemigrations` создавать миграции, но `./manage.py migrate` опрашивает его, чтобы пропускать ReadOnly БД.
Но в Django есть еще уровни защиты:
— вывод `inspectdb` по умолчанию содержит `managed=False` (читай — read only) для всех генерируемых моделей
— `migrate` по умолчанию применяется только к `default` БД

Я думаю если программист руками исправил `managed` на `True` и потом запускает `migrate --database=some_non_default_db` то он явно хочет чтото мигрировать, и еще один триггер в DB Router его уже не остановит.

`allow_migrate` скорее пригодится в конфигурации, где баз данных больше чем две, и некоторые из них read_only а некоторые — нет.

Но конечно лучше всего резать доступ уже на уровне access_rights пользователя БД.
Sign up to leave a comment.

Articles