Философия дизайна

Этот документ объясняет некоторые из фундаментальных идей, которыми руководствуются при работе с фреймворком Django. Его цель - объяснить уже сделанное и направить в нужную сторону.

Основы

Слабое связывание

Фундаментальная основа стека Django - это слабая связанность и сильное зацепление (loose coupling and tight cohesion). Отдельным слоям фреймворка не следует “знать” друг о друге, если в этом нет острой необходимости.

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

Django поставляется с пакетом приложений, который представляет из себя кусочки, для удобства независимые настолько, насколько это возможно.

Меньше кода

Приложения Django должны использовать настолько мало кода, насколько возможно; следует избегать шаблонных кусков. Django должен в полной мере использовать все динамические возможности Python’а, например интроспекцию.

Быстрая разработка

К Web фреймворку 21-го века ставятся жесткие требования. Одним из них является время разработки. Django должен позволять разрабатывать Web приложения невероятно быстро.

Не повторяйтесь (DRY)

Каждая отдельная концепция и/или кусок данных следует хранить в одном и лишь одном месте. Избыточность - плохо. Нормализация - хорошо.

Фреймворк, в пределах разумного, должен использовать как можно больше из как можно меньшего.

Явное лучше чем неявное

Этот принцип Python’а упоминается в PEP 20, и это значит, что Django не должен творить слишком много “магии.” Она не должна происходить без явной на то причины. Магию стоит использовать только в том случае, если она дает значительные преимущества, недостижимые другими путями, и, кроме того, не вводит в заблуждение разработчиков, пытающихся понять, как же она работает.

Логичность

Фреймворк должен быть логичным на всех уровнях: начиная от стиля программирования на Python’е и заканчивая опытом использования Django

Модели

Явное лучше чем неявное

Поведение поля (fields) не должно основываться исключительно на его имени. Это требует слишком много знаний о системе и ведет ко множеству ошибок. Вместо этого используйте в качестве ключевых слов аргументы и, в некоторых случаях, тип поля.

Включайте всю логику предметной области

Модель должна инкапсулировать каждый аспект “объекта”, поэтому придерживайтесь патерна Active Record Мартина Фаулера

Вот почему информация, описывающая модель и логику ее работы (например, хорошо читаемое имя, настройки по умолчанию и др.), определена в классе модели; все данные, необходимые для понимания работы модели, следует хранить в самой модели.

API баз данных

Главные задачи ядра баз данных:

Эффективность SQL

SQL запросы должны выполняться как можно реже, и должны быть оптимизированы.

Поэтому разработчик должен делать вызов save() явным, а не ждать пока фреймворк сохранит данные сам.

Кроме того, это объясняет, для чего нужны метод select_related() класса QuerySet. Это альтернативный способ оптимизации стандартной задачи получения всех связанных объектов.

Немногословный, но мощный синтаксис

API базы данных должен поддерживать богатые выразительные средства, используя при этом как можно меньше синтаксиса, кроме того не следует полагаться на импорт других можулей и объектов

Слияние выполняется автоматически, когда это необходимо.

Каждый объект должен иметь возможность получить доступ ко всем связанным и общесистемным объектам. Такой доступ должен работать в обоих направлениях.

Возможность легко использовать SQL, если это необходимо

API базы данных должен упрощать работу с базой данных, а не замыть её полностью на себе. Фреймворк должен позволять легко использовать SQL – полностью написать запрос, или указать только WHERE при вызове API.

Использование URL

Слабое связывание

ULR-адреса в приложениях Django не следует как-либо привязывать к коду Python’а. URL-адреса в именах функций Python’а совершенно ненужны и уродливы.

URL-адреса Django должны позволять формировать разные URL для одного и того же приложения в разных контекстах. Например, один сайт может поместить истории в /stories/, в то время как другой использует /news/.

Бесконечная гибкость

URL должны быть максимально гибкими и позволять абсолютно любую форму URL-адреса.

Поощряйте “best practices”

Фреймворк должен подталкивать разработчика к использованию красивых и логичных URL-адресов.

Не используйте расширение файла в URL страниц.

Использующие запятые в URL, заслуживают сурового наказания.

Дефинитивные URL-адреса

Технически, foo.com/bar и foo.com/bar/ – это два разных URL-адреса, и поисковые роботы (и некоторые утилиты анализа трафика) будут воспринимать их как отдельные страницы, поэтому Django должен позаботиться о “нормализации” адресов.

Вот для чего была создана настройка APPEND_SLASH.

Шаблоны Django

Отделяйте логику от представления

Система шаблонов, как мы видим, являет собой контроллер представления и связанную с этим логику, и ничего более. Шаблоны не поддерживают какую либо функциональность, выходящую за рамки отображения данных

Откажитесь от избыточности

The majority of dynamic websites use some sort of common sitewide design – a common header, footer, navigation bar, etc. The Django template system should make it easy to store those elements in a single place, eliminating duplicate code.

Это основа философии наследования шаблонов.

Не зацикливайтесь на HTML

Шаблоны следует проектировать так, чтобы была возможность генерировать представление данных в любых текстовых форматах, а не только в HTML

XML не лучший способ описания шаблонов

Использование XML в качестве основы для парсера шаблонов приведет Вас в новый безграничный мир человеческих ошибок, и, кроме того, потребует больших затрат при обработке шаблона

Предполагается, что верстальщики знают свое дело

Проектируйте шаблон так, чтобы его редактирование не требовало обязательного использования реакторов WYSIWYG, таких как Dreamweaver, для красивого отображения. Код должен хорошо выглядеть и таким, какой он есть. Django позволяет автору шаблона создавать его в обычном текстовом редакторе.

Очевидная обработка пробелов

Шаблоны не должны творить магию с пробелами. Если шаблон включает пробел, то система обрабатывает пробелы также как и обычный текст - просто отображает его. Любые пробелы, не включенные в тег, отображаются как есть.

Не изобретайте язык программирования

The goal is not to invent a programming language. The goal is to offer just enough programming-esque functionality, such as branching and looping, that is essential for making presentation-related decisions. The Django Template Language (DTL) aims to avoid advanced logic.

Система шаблонов Django подразумевает, что шаблоны чаще всего создаются дизайнерами, не программистами, поэтому написание шаблона не привязано к знанию сиснаксиса Python’а

Безопасность и защита

Из коробки система шаблонов не позволяет выполнять код, так или иначе причиняющий вред данным, например их удаление

И это другая причина, почему шаблоны Django не позволяют напрямую работать с кодом Python’а

Расширяемость

Система шаблонов предполагает, что разработчику может понажобиться расширить спектр используемых технологий

И эта философия основывается на кастомных тегах и фильтрах

Представление

Простота

Создание представления следует делать таким же простым как и написание функции Python’а. Разработчики

Использование объектов запроса

Представление должно иметь доступ к объекту запроса – объекту, хранящему метаданные о текущем запросе. Объект следует передавать непосредствено в функцию представления. Это лучше, чем если бы представление получало данные от запроса через какую либо глобальную переменную. Все это делает простым и прозрачным тестирование представления посредством передачи ему “ложных” данных

Слабое связывание

Представление не должно заботиться о том, какой шаблон использует разработчик, или даже будут ли шаблоны вообще использоваться.

Разграничивайте GET и POST запросы

GET и POST сильно отличаются, поэтому разработчику следует разделять их использование. Фреймворк должен легко отличать данных GET и POST запросов.

Ядро кэша

Задачи ядра кэша Django:

Меньше кода

Кэш создается настолько быстрым, насколько это возможно. Таким образом, весь код фреймворка, затрагивающий работу с кэшем, следует сводить к абсолютному минимуму, особенно касательно get() запросов

Логичность

API кэша проектируется так, чтобы обеспечить единый интерфейс, позволяющий однообразно работать с различными реализациями кэша

Расширяемость

Обычно оставляют возможность расширения API кэша в будущем для нужд разработчика (например смотрите Преобразование ключа кэша)