10 главных ошибок, которые допускают разработчики Django

Опубликовано: 2022-03-11

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

Django — это бесплатная веб-инфраструктура Python с открытым исходным кодом, которая помогает решать распространенные задачи разработки и позволяет создавать гибкие, хорошо структурированные приложения. Django имеет множество современных функций из коробки. Лично для меня функции администрирования, объектно-реляционного сопоставления (ORM), маршрутизации и шаблонов сделали Django моим первым выбором, потому что приложения требуют много работы, и, хотя я наслаждаюсь своей работой так же, как и любой разработчик, я хочу тратить как можно меньше времени на эти основные повторяющиеся задачи. Django позволяет вам делать все это без ущерба для гибкости.

Отличительной особенностью Django является мощный настраиваемый интерфейс администратора, который автоматически (автоматически?) создается из схемы ваших моделей и моделей панели администратора, позволяя вам почувствовать себя волшебником. Через интерфейс администратора пользователь может настроить множество вещей, включая список управления доступом (ACL), разрешения и действия на уровне строк, фильтры, заказы, виджеты, формы, дополнительные вспомогательные URL-адреса и все, что вы можете себе представить. Я считаю, что каждому приложению требуется панель администратора — если еще нет, это просто вопрос времени, когда она понадобится вашему основному приложению. С администратором Django вы можете создать его быстро и гибко.

Django имеет мощную ORM, которая работает со всеми основными базами данных из коробки. Поскольку он ленивый, он попадает в вашу базу данных только тогда, когда вам это нужно, в отличие от других ORM. Он поддерживает все основные инструкции (и функции) SQL, которые вы можете использовать из исходного кода Python, и очень удобен благодаря возможностям Python.

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

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

Ошибка № 1: Использование глобальной системной среды Python для зависимостей проекта

Не используйте глобальную среду Python для зависимостей проекта, так как это может привести к конфликтам зависимостей. Python не может использовать несколько версий пакетов одновременно. Это может быть проблемой, если для разных проектов требуются разные несовместимые версии одного и того же пакета.

Эту ошибку обычно совершают новые разработчики Python и Django, которые не знают о функциях изоляции среды Python.

Существует множество способов изолировать вашу среду, но наиболее распространенными являются следующие:

  • virtualenv: пакет Python, который создает папку среды Python и содержит сценарии для [де]активации среды и управления установленными пакетами Python в среде. Это мой любимый метод, потому что это самый простой способ выполнить работу. Обычно я создаю среду рядом с папкой проекта.
  • virtualenvwrapper: пакет Python, который устанавливается глобально и предоставляет набор инструментов для создания/удаления/активации и т. д. виртуальные среды. Все виртуальные среды хранятся в одной папке (которую можно переопределить с помощью переменной среды WORKON_HOME). Я не вижу никаких преимуществ в использовании virtualenvwrapper вместо virtualenv .
  • Виртуальные машины (ВМ): нет большей изоляции, чем целая виртуальная машина, выделенная для вашего приложения. Существует множество инструментов на выбор, включая VirtualBox (бесплатно), VMware, Parallels и Proxmox (мой личный фаворит, и у него есть бесплатная версия). В сочетании с инструментом автоматизации виртуальных машин, таким как Vagrant, это может быть чрезвычайно мощным решением.
  • Контейнеры. Последние несколько лет я использую Docker почти в каждом проекте, особенно в каждом новом проекте, который начинаю с нуля. Docker — это удивительный инструмент, который предоставляет множество функций и имеет множество сторонних инструментов для автоматизации контейнеров. Он имеет функцию кэширования слоев, которая делает перестроение ваших контейнеров чрезвычайно быстрым. В контейнерах я использую глобальную системную среду Python, потому что каждый контейнер имеет свою файловую систему, а проекты изолированы на высоком уровне. Docker позволяет новым членам команды быстрее начать работу над проектом, особенно если у них есть опыт работы с Docker.

Если вы спросите меня, я предпочитаю пакет virtualenv Python и контейнеры Docker для изоляции зависимостей проекта и управления ими.

Ошибка № 2: Не закреплять зависимости проекта в файле requirements.txt

Каждый новый проект Python должен начинаться с файла requirements.txt и новой изолированной среды. Обычно вы устанавливаете все пакеты через pip/easy_install , но никогда не забывайте добавлять их и в ваш файл requirements.txt . Это упрощает ( возможно , более подходящее) развертывание вашего проекта на серверах или позволяет члену команды загружать проект на своем компьютере.

Кроме того, не менее важно закрепить конкретную версию ваших зависимостей в файле requirements.txt . Обычно разные версии пакета предоставляют разные модули, функции и параметры функций; даже незначительное изменение версии в зависимости может сломать ваш пакет. Это очень серьезная проблема, если ваш проект работает и у вас регулярно запланированы развертывания, поскольку без управления версиями ваша система сборки всегда будет устанавливать последнюю доступную версию пакета.

Всегда закрепляйте свои пакеты для производства! Лично я использую очень хороший инструмент под названием pip-tools, который помогает мне в этом. Он предоставляет набор инструментов командной строки, которые помогают управлять вашими зависимостями. Он автоматически генерирует файл requirements.txt , который закрепляет не только ваши зависимости, но и все ваше дерево зависимостей, которое включает в себя зависимости ваших зависимостей.

Иногда вы хотите обновить только некоторые пакеты из вашего списка зависимостей (например, только Django/Flask/любой фреймворк или утилиту), если вы использовали «заморозку пакетов», вы не знаете, какие зависимости для каких пакетов, и поэтому вы не могу обновить зависимость. Однако с помощью pip-tools он автоматически закрепляет пакеты в зависимости от того, какую зависимость вы закрепили, поэтому он автоматически решает, какие пакеты необходимо обновить. В качестве бонуса вы также точно знаете, какой пакет пришел из какой зависимости, благодаря тому, как он помечает их комментариями в файле requirements.txt .

Чтобы быть особенно осторожным, неплохо также сделать резервную копию исходных файлов зависимостей! Сохраните копию в своей файловой системе, в папке, управляемой Git, в папке S3, на FTP, SFTP — где угодно, но всегда под рукой. Были случаи, когда относительно небольшой пакет, не включенный в список, ломал большое количество пакетов в npm. Pip услужливо предоставляет инструмент для загрузки всех необходимых зависимостей в виде исходных файлов. Узнайте больше, запустив pip help download .

Ошибка № 3: использование функций Python в старом стиле вместо представлений на основе классов

Иногда полезно использовать небольшую функцию Python в файле views.py приложения, особенно для тестов или служебных представлений, но, как правило, в своих приложениях следует использовать представления на основе классов (CBV).

CBV — это общие представления, которые предоставляют абстрактные классы, реализующие общие задачи веб-разработки, созданные профессионалами и охватывающие все распространенные модели поведения. У них потрясающий структурированный API, и вы можете использовать все преимущества объектно-ориентированного программирования при использовании CBV. Это делает ваш исходный код более понятным и читаемым. Забудьте о боли использования стандартных функций представления Django для списков, операций CRUD, обработки форм и т. д. Вы просто расширяете подходящий CBV для своего представления и переопределяете свойства или функции класса (обычно функция возвращает свойство, и вы можете добавить туда любую логику, что делает спагетти из вашего исходного кода в случае использования функций представления вместо CBV), которые настраивают поведение представления.

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

Я создал пакет под названием Django Template Names, который стандартизирует имена шаблонов для ваших представлений на основе имени приложения и имени класса представления. Я использую его каждый день, и это экономит мне много времени на придумывание имен. Просто поместите миксин в свой CBV — class Detail(TemplateNames, DetailView): — и он начнет работать! Конечно, вы можете переопределить мои функции и добавить шаблоны, адаптированные для мобильных устройств, различные шаблоны для пользовательских агентов или что-то еще, что вы хотите.

Ошибка № 4: Написание толстых представлений и тощих моделей

Написание логики вашего приложения в представлениях вместо моделей означает, что вы написали код, принадлежащий вашей модели, в представление, сделав его «толстым», а вашу модель — «тощей».

Вам следует писать толстые модели, тощие взгляды.

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

Это также упрощает модульное тестирование вашего кода, поскольку вы можете тестировать логику электронной почты в одном месте, а не повторно в каждом контроллере, где это происходит.

Подробнее о проблеме можно прочитать в проекте Django Best Practices. Решение простое: напишите толстые модели и тонкие представления, так что давайте сделаем это в вашем следующем проекте (или рефакторинге вашего текущего).

Ошибка № 5: огромный неуправляемый файл настроек

Даже новый файл настроек проекта Django имеет множество настроек. В реальном проекте файл настроек разрастается до 700+ строк конфигурации, и его будет сложно поддерживать, особенно когда вашей среде разработки, производственной и промежуточной средам нужны настраиваемые конфигурации.

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

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

Посмотрите пример минимальной конфигурации:

 from split_settings.tools import optional, include include( 'components/base.py', 'components/database.py', 'components/*.py', # the project different envs settings optional('envs/devel/*.py'), optional('envs/production/*.py'), optional('envs/staging/*.py'), # for any local settings optional('local_settings.py'), )

Ошибка № 6: приложение «все в одном», плохая структура приложения и неправильное размещение ресурсов

Любой проект Django состоит из нескольких приложений. В нотации Django приложение — это пакет Python, который содержит как минимум файлы __init__.py и models.py ; в последних версиях Django models.py больше не требуется. __init__.py достаточно.

Приложения Django могут содержать модули Python, специфичные для Django модули (представления, URL-адреса, модели, администрирование, формы, теги шаблонов и т. д.), статические файлы, шаблоны, миграции баз данных, команды управления, модульные тесты и многое другое. Вы должны разделить свои монолитные приложения на небольшие повторно используемые приложения, используя простую логику. Вы должны быть в состоянии описать всю цель приложения в одном или двух коротких предложениях. Например: «Позволяет пользователям регистрироваться и активировать свою учетную запись по электронной почте».

Хорошей идеей будет назвать папку project и поместить приложения в project/apps/ . Затем поместите все зависимости приложений в их собственные подпапки.

Примеры:

  • Статические файлы: project/apps/appname/static/appname/
  • Теги шаблона: project/apps/appname/templatetags/appname.py
  • Файлы шаблонов: project/apps/appname/templates/appname/

Всегда добавляйте префикс к имени приложения во вложенных папках, потому что все статические папки объединены в одну папку, и, если два или более приложений имеют файл js/core.js , последнее приложение в settings.INSTALLED_APPLICATIONS переопределит предыдущие. Однажды у меня была эта ошибка в моем текущем проекте, и я потерял около шести часов на отладку, пока не понял, что другой разработчик переопределил static/admin/js/core.js потому что команда реализовывала пользовательскую панель администратора SPA и называла свои файлы таким же образом.

Вот пример структуры портального приложения с большим количеством ресурсов и модулей Python.

 root@c5b96c395cfb:/test# tree project/apps/portal/ project/apps/portal/ ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ ├── __init__.py │ └── update_portal_feeds.py ├── migrations │ └── __init__.py ├── models.py ├── static │ └── portal │ ├── css │ ├── img │ └── js ├── templates │ └── portal │ └── index.html ├── templatetags │ ├── __init__.py │ └── portal.py ├── tests.py ├── urls.py └── views.py 11 directories, 14 files

Используя такую ​​структуру, вы можете в любой момент экспортировать приложение в другой пакет Python и использовать его снова. Вы даже можете опубликовать его в PyPi как пакет с открытым исходным кодом или переместить в другую папку.

Вы получите такую ​​структуру проекта:

 root@c5b96c395cfb:/test# tree -L 3 . ├── deploy │ ├── chef │ └── docker │ ├── devel │ └── production ├── docs ├── logs ├── manage.py ├── media ├── project │ ├── __init__.py │ ├── apps │ │ ├── auth │ │ ├── blog │ │ ├── faq │ │ ├── pages │ │ ├── portal │ │ └── users │ ├── conf │ ├── settings.py │ ├── static │ ├── templates │ ├── urls.py │ └── wsgi.py └── static └── admin ├── css ├── fonts ├── img └── js 25 directories, 5 files

В реальном проекте, конечно, будет сложнее, но такая структура делает все проще и чище.

Ошибка № 7: STATICFILES_DIRS и STATIC_ROOT сбивают с толку начинающих разработчиков Django

STATICFILES_DIRS? STATIC_ROOT?

Статические файлы — это активы, которые не изменяются при использовании приложения, например, JavaScript, CSS, изображения, шрифты и т. д. В Django они «собираются» в общий каталог только во время процесса развертывания.

В режиме разработки — python manage.py runserver — Django ищет статические файлы, используя настройку STATICFILES_FINDERS . По умолчанию он пытается найти запрошенный статический файл в папках, перечисленных в параметре STATICFILES_DIRS . В случае сбоя Django пытается найти файл с помощью django.contrib.staticfiles.finders.AppDirectoriesFinder , который просматривает static папку каждого установленного приложения в проекте. Это позволяет вам писать повторно используемые приложения, которые поставляются со своими собственными статическими файлами.

В производственной среде вы обслуживаете свои статические данные с помощью автономного веб-сервера, такого как Nginx. Веб-сервер ничего не знает о структуре приложений проекта Django или о папках, в которых распространяются ваши статические файлы. К счастью, Django предоставляет вам команду управления сбором статических данных python manage.py collectstatic , которая проходит через STATICFILES_FINDERS и копирует все статические файлы из static приложений. папки и папки, перечисленные в STATICFILES_DIRS , в каталог, указанный в параметре STATIC_ROOT . Это позволяет разрешать статические файловые ресурсы, используя ту же логику, что и сервер режима разработки Django, и имеет все статические файлы в одном месте для вашего веб-сервера.

Не забудьте запустить collectstatic в рабочей среде!

Ошибка №8: STATICFILES_STORAGE умолчанию, загрузчики шаблонов Django в продакшене

STATICFILES_STORAGE

Давайте поговорим об управлении активами производственной среды. Мы можем обеспечить наилучшее взаимодействие с пользователем, если будем использовать политику «активы никогда не истекают» (подробнее о которой вы можете прочитать здесь). Это означает, что все наши статические файлы должны кэшироваться веб-браузерами на недели, месяцы или даже годы. Другими словами, ваши пользователи должны загружать ваши активы только один раз!

Это круто, и мы можем сделать это с помощью нескольких строк в конфигурации Nginx для нашей папки со статическими файлами, но как насчет инвалидации кеша? Если пользователь загрузит наши ресурсы только один раз, что произойдет, если вы обновите свой логотип, шрифты, JavaScript или цвет текста для элемента в меню? Чтобы обойти это, вы должны генерировать уникальные URL-адреса и имена файлов для наших статических файлов при каждом развертывании!

Мы можем сделать это, просто используя ManifestStaticFilesStorage как STATICFILES_STORAGE (будьте осторожны, хэширование включается только в режиме DEBUG=false ) и запустив команду управления collectstatic , описанную выше. Это уменьшит количество запросов ресурсов на ваш рабочий веб-сайт и значительно ускорит отображение вашего веб-сайта.

Кэшированный загрузчик шаблонов Django

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

Ознакомьтесь с разделом конфигурации cached.Loader , где есть хороший пример и подробная информация о том, как это сделать. Не используйте загрузчик в режиме разработки, поскольку он не перезагружает проанализированные шаблоны из файловой системы; вам нужно будет перезапустить проект, используя python manage.py startapp при каждом изменении шаблона. Это может раздражать во время разработки, но идеально подходит для производственной среды.

Ошибка № 9: Чистые Python-скрипты для утилит или скриптов

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

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

Ошибка № 10: заново изобретать колесо

Не изобретайте велосипед

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

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

Для начала вот список моих собственных общедоступных пакетов для Django:

  • URL-адрес Django Macros упрощает запись (и чтение) шаблонов URL-адресов в приложениях Django с помощью макросов.
  • Django Templates Names — это небольшое дополнение, которое позволяет вам легко стандартизировать имена шаблонов CBV.
  • django-split-settings позволяет организовать настройки Django в несколько файлов и каталогов. Легко переопределять и изменять настройки. Используйте подстановочные знаки в путях к файлам настроек и помечайте файлы настроек как необязательные.

Не повторяйтесь (СУХОЙ)!

Мне очень нравится методология DRY; вот почему я создал скелет Django как удобный инструмент, который имеет несколько очень полезных функций из коробки:

  • Образы Docker для разработки/производства, управляемые docker-compose, что позволяет легко организовать список контейнеров.
  • Простой сценарий Fabric для производственного развертывания.
  • Конфигурация пакета Django Split Settings с настройками для базовых и локальных источников.
  • Webpack интегрирован в проект — только папка dist будет собрана Django по команде collectstatic .
  • Настроены все основные параметры и функции Django, такие как кэшируемые шаблоны Django в производстве, хешированные статические файлы, встроенная панель инструментов отладки, ведение журнала и т. д.

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