Лучший подход к загрузке определенных адресов (представлений) в проекте Django
У меня есть приложение Django, которое раскрывает следующие представления: A,B,C...Z. Это приложение развернуто на MACHINE-1.
Появилось новое бизнес-требование развернуть на MACHINE-2 то же самое приложение Django, но с подмножеством этих представлений, скажем, A, B и C.
Моим простым решением было установить переменную config (RUN_ON_MACHINE_2=True
для второго случая и False
для первого). В заключение, файл urls.py
выглядит примерно так (пожалуйста, обратите внимание, что я ассимилирую представления с путями здесь только для того, чтобы сделать его короче):
urlpatterns = [A, B, C, ... Z]
# If the env var is set to True then only load a subset of the views
if config.RUN_ON_MACHINE_2:
urlpatterns = [A, B, C]
Тесты работают нормально, потому что они всегда выполняются для [A,B,C ... Z], которые, конечно, включают [A, B, C].
Однако, некоторые новые бизнес-требования требуют внести изменения в представление A. Я мог бы реализовать изменения в представлении A, разветвляя код по переменной config.RUN_ON_MACHINE_2
, но я пришел к выводу, что гораздо лучше создать новое представление A_ForMachine2
, которое реализует только необходимые вещи для MACHINE_2. A_ForMachine2
должен иметь тот же интерфейс, что и представление A
, и должен быть смонтирован по тому же пути. Таким образом, новый urls.py
будет выглядеть так:
urlpatterns = [A, B, C, ... Z]
# If the env var is set to True then only load a subset of the views
if config.RUN_ON_MACHINE_2:
# A_ForMachine2 is mounted on the same path as A
urlpatterns = [A_ForMachine2, B, C]
Теперь у меня есть 2 представления, которые установлены по одному и тому же пути, поэтому они имеют одинаковый URL.
Теперь мои api тесты тестируют только представление A
, потому что по умолчанию config.RUN_ON_MACHINE_2
имеет значение False.
Я пытался исправить config.RUN_ON_MACHINE_2
в своем тестовом примере, но, насколько я понимаю, при запуске тестов приложение уже загружено всеми ссылками A,B,...Z, поэтому исправлять бесполезно.
Каков чистый способ иметь приложение Django (в моем случае приложение DRF), которое загружает различные URL при запуске (в зависимости от некоторой переменной env), имея все его представления легко тестируемыми?
Выпьем!
ROOT_URLCONF в помощь
Здесь документация
Во-первых, никогда не используйте подобную архитектуру if-else для различных машинных сред.
Всегда добавляйте переменную SETTINGS
в .env файл и создавайте различные файлы настроек как для dev
, qa
, stage
, prod
или local
. В вашем случае создайте разные файлы настроек для Machine-1
и Machine-2
.
Затем в настройках вы обновляете ROOT_URLCONF
в соответствии с урлами, которые вам нужны для различных сред.
Ваша основная папка urls.py
будет преобразована в папку urls
, куда вы можете добавить урлы с машинным именем. Затем добавьте путь к ROOT_URLCONF
в соответствующие настройки.
Ваша структура urls
будет выглядеть следующим образом:
urls
├── __init__.py
├── common.py
├── local.py
└── production.py
И ваш файл различных настроек будет иметь такие свойства:
# settings/local.py
ROOT_URLCONF = 'urls.local'
и это
# settings/production.py
ROOT_URLCONF = 'urls.production'
Основные изменения произойдут в urlspattern
:
# urls/local.py
from .common.py import urlpatterns as common_urlpatterns
urlpatterns = common_urlpatterns + [
url(r'^A-view-path/', include(app_1.urls_for_A)),
]
Вы можете сохранить оба представления, имеющие немного разную функциональность с разными именами. Но добавьте один и тот же url к машине один с одним представлением и машине два с другим представлением.
Вот похожий пост. Я скопировал некоторые ссылки о структуре папок отсюда. У меня была та же проблема, так как мне нужны урлы профилирования кода только на тестовом и локальном экземпляре, но не на dev, qa и prod экземплярах. Тогда это очень помогло.
Если вы добавите архитектуру if-else сейчас, то в будущем у вас будут проблемы с масштабируемостью. А если вы покинете компанию, другие новые разработчики будут большую часть времени чесать затылки, так как никто не будет знать, почему все происходит именно так.
Не забудьте добавить комментарии, чтобы другие знали о ваших намерениях.