Заманчиво рассматривать DEBUG как флаг функции. Многие разработчики считают это аналогом если приложение не работает в рабочей среде. Однако использование DEBUG для изменения потока кода усложняет тестирование и поддержку кодовой базы.

В качестве конкретного примера предположим, что мы хотим активировать администратора Django только в локальной разработке, чтобы уменьшить площадь поверхности для атак хакеров в рабочей среде. Мы могли бы сделать это:

from django.conf import settings
from django.contrib import admin
 
urlpatterns = […]
# not exposing admin to prod so it can’t be hacked
if settings.DEBUG:
    urlpatterns.append(path(‘admin/’, admin.site.urls))

Это будет работать, но код будет труднее тестировать изолированно, потому что значение DEBUG меняет другое поведение Django, включая обработку ошибок (должны ли мы видеть подробный отчет о сбоях в браузере? Должны ли ошибки быть отправлены по электронной почте администраторам?). Поэтому вместо использования DEBUG таким образом рассмотрите возможность использования флага функции:

from django.conf import settings
from django.contrib import admin
 
urlpatterns = […]
# not exposing admin to prod so it can’t be hacked
if settings.IS_ADMIN_ENABLED:
    urlpatterns.append(path(‘admin/’, admin.site.urls))

Причиной этой сложности является тот факт, что DEBUG предназначен для переключения, должен ли Django работать в режиме отладки. На самом деле он предназначен для переключения поведения framework и framework library, а не кода приложения. Использование DEBUG для управления поведением кода приложения, созданного поверх фреймворка, усложняет поддержку и тестирование кодовой базы. Подобное смешение слоев и обязанностей добавляет сложности.

Например, DEBUG=True показывает подробные страницы ошибок для использования во время локальной разработки, а DEBUG=False может привести к тому, что ошибка будет отправлена ​​по электронной почте в settings.ADMINS. Вы хотите вызвать одно из этих поведенческих изменений при тестировании кода? Наверное, нет, так как это неудобно, а также противоречит принципу наименьшей неожиданности.

Помимо сложностей в тестировании, Приложение с двенадцатью факторами предлагает стремиться к паритету разработки и производства. Использование DEBUG для управления тем, какой блок кода запускает приложение, предотвращает четность dev/prod, поскольку большинство разработчиков не будут тестировать или запускать свою локальную среду с DEBUG=False. Чтобы решить эту проблему, рассмотрите возможность добавления флага функции специально для этой проверки, который вы можете легко переключать во время модульных тестов и без каких-либо других побочных эффектов, присущих DEBUG.

Если мы обнаружим эту проблему в вашем запросе на включение GitHub, мы дадим следующий совет:

Реализация флага функции

12-факторное приложение предполагает, что флаги функций можно включать и выключать с помощью переменных среды. Вы можете установить библиотеку для анализа переменных среды или сделать что-то вроде:

# settings.py
from ast import iteral_eval
from os import getenv
IS_ADMIN_ENABLED = literal_eval(getenv('IS_ADMIN_ENABLED', 'False'))

ast.iteral_eval — это та полезная функция, которая вам всегда была нужна, но вы никогда не знали, что Python предоставляет ее из коробки. Он может преобразовать строку False в логическое значение False, а строку True — в логическое значение True.

Подпишитесь на нас в Twitter, чтобы узнать больше о Django

Есть ли в вашей кодовой базе Django такой технический долг?

Django Doctor может найти и исправить более 40 типов распространенных технических долгов Django и даже может просмотреть ваши запросы GitHub Pull Requests для вас.