Структура каталогов для проекта (в частности на Flask)


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

Корень

И так мы взялись за проект. Пусть это будет самый простой проект myapp. Создаём для него каталог в основной папке для разработки (у меня это Devel).

mkdir myapp
cd myapp

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

Git

Инициализируем пустой репозиторий

git init

.gitignore

# Игнорировать байткод
*.pyc
*.pyo

**/__pycache__/

# Игнорировать каталог с файлами настройки
**/config/

# Игнорировать каталог с данными и логами
**/data/
**/logs/

# Игнорировать каталог с исполнимыми файлами и модулями (если таковой имеется)
**/bin/

Прочти меня

Следующим шагом идёт создание обязательного файла README. В этом файле хранится основное и ключевое описание нашего будущего проекта. Некоторые делают файл в виде text/plain с названием README.txt. На крупных порталах репозитариях принят за стандарт Markdown с названием README.md. Я же предпочитаю html, т.к. мне удобнее делать цветовые выделения, вставлять ссылки, картинки и другие мультимедиа, открывать в браузере, вставлять куски кода в тегах <pre> и <code>, использовать готовые фреймворки типа Bootstrap для оформления и другой магии вне Хогвардса. Соответственно и название README.html

touch README.html

Если проект ведётся несколькими командами, то рекомендую каждой команде иметь свой README файл внутри каждого разрабатываемого независимо модуля, компонента, библиотеки и т.д.

Приложение

Основной каталог приложения называю так же, как и каталог проекта. В случае этой статьи myapp

mkdir myapp
touch myapp/__init__.py

Модули и компоненты

Внутри каталога приложения стандартно создаются __init__.py, содержащий код инициализации приложения и подключения всех необходимых частей к приложению. В частности это Blueprints для одноветочных URL или namespace для логики отдельного сервиса, но с разными URL (простым примером может служить создание namespace для сервиса статей блога, где явно имеются разные пути вида /pages и /page/ID)

mkdir myapp/bp_component
touch myapp/bp_component/__init__.py

или

mkdir myapp/ns_component
touch myapp/ns_component/__init__.py

Модель БД

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

mkdir myapp/models
touch myapp/models/__init__.py
touch myapp/models/page.py

Шаблоны для шаблонизатора

Для некоторых приложений (в основном веб-приложений) характерно использование шаблонов для генерации конечных страниц. Так как основной целью является отделение исполняемого кода от представления данных, то данный шаг поможет в работе команды сэкономить много времени, сил и денег, обеспечив возможность параллельной работы программистов и дизайнеров.

mkdir myapp/templates
mkdir myapp/templates/html
mkdir myapp/templates/js
mkdir myapp/templates/css

Замечу, что в данном случае подкаталог js и css служат не для хранения статических библиотек JavaScript или стилей CSS, а именно для изменяемого кода, кода с параметрами или кода для вставки. Например если имеется компонент прорисовки календаря с подключением допфункционала к кнопкам, то будет гораздо удобнее в js положить компонент календаря, а в html файлах делать включения компонента, но с нужными параметрами. Возможно это покажется кому-то говнокодом, но это гораздо лучше, чем создать готовую статическую библиотеку календаря, а через полгода-год понять, что требуется добавить ещё пару тройку свойств и методов к компоненту (например сделать datepicker не только в виде одного месяца, но и добавить возможность превратить в календарь на год), а какая магия была внутри никто и не вспомнит. Вставки дадут больше прозрачности.

Статика

Здесь все основные никогда не меняющиеся (или меняющиеся крайне редко) стили, картинки, звуки, JS библиотеки и фреймворки.

mkdir myapp/static
mkdir myapp/static/css
mkdir myapp/static/js
mkdir myapp/static/images

Библиотека функций

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

mkdir myapp/lib
touch myapp/lib/__init__.py

Настройки и конфигурирование

Как хранить настройки, определяющие глобальные параметры приложения? Сколько на этот счет было баталий и не счесть. Без деталей как делаю я: храню в виде Python модуля отдельным каталогом. Внутри файлы для разных режимов запуска.

mkdir config
echo "CONFIG = 'config.devel'" > config/__init__.py
touch config/devel.py
touch config/prod.py

Почему py? Да потому, что никому не сдался парсинг XML, YAML, INI и другой чепухи, когда под рукой достаточно легко создавать переменные вида:

import os

DEBUG = True

TITLE = 'SpecialistOff.NET'

DIR_BASE = '/'.join(os.path.dirname(os.path.abspath(__file__)).split('/')[:-1])
DIR_DATA = DIR_BASE + '/data'
DIR_FILES = DIR_DATA + '/files'

MIMETYPES = {
    'gif': 'image/gif',
    'jpg': 'image/jpeg',
    'jpeg': 'image/jpeg',
    'png': 'image/png',
    'txt': 'text/plain'
}

SERVERS = [
    {'name': 'server1', 'IP': '8.8.8.8', 'port': '80'}
]

Данные

Подгружаемые в процессе работы файлы, логи и другие данные хранятся в отдельном каталоге data

mkdir data
mkdir data/files

Тестирование

Тестовые модули и фикстуры

mkdir tests
mkdir tests/fixture
touch tests/__init__.py
touch test.py
chmod +x test.py

Документация

Вся документация по проекту должна храниться отдельно. Я использую для этого каталог doc и храню как статические веб-страницы с входной точкой index.html. Это удобно тем, что я могу расшарить отдельный каталог документации через любой веб-сервер. Или просмотреть прямо из каталога любым веб-браузером (в том числе и консольными типа lynx, elinks).

mkdir doc
touch doc/index.html

Развертывание

Здесь всё зависит от задач. И в комментариях (по моему скромному мнению) не особенно нуждается.

mkdir deploy
touch deploy/requirements.txt
touch deploy/build.sh
mkdir deploy/config
touch deploy/config/__init__.py
touch deploy/config/demo.py
mkdir deploy/cron
touch deploy/cron/myapp
mkdir deploy/docker
touch deploy/docker/Dockerfile
touch deploy/docker/docker-compose.yml
mkdir deploy/nginx
touch deploy/nginx/myapp.conf
mkdir deploy/uwsgi
touch deploy/uwsgi/conf.ini
mkdir deploy/uwsgi/conf.d
touch deploy/uwsgi/conf.d/myapp.conf

Логирование

Сюда можно складывать логи при тестовых запусках или выводы самого приложения.

mkdir logs

Вспомогательные скрипты и утилиты

mkdir utils
touch utils/useradd.py
chmod +x utils/useradd.py

Вместо заключения

В принципе это все. Почему я так немногословен? Потому, что код скажет за меня лучше, чем я сам. Остальные мои комментарии могут либо запутать, либо разжечь споры о том, какой подход будет лучше/хуже

И на Хабре https://habr.com/post/421887/


RemiZOffAlex   Создано: 2018-08-31   Обновлено: 2018-10-29