В разработке своих проектов на Django я придерживаюсь архитектуры, близкой к той, которую описал Мальколм Трединник в своей статье "Django Tip: Developing Without Projects". Странно звучит, да, разработка проектов используя методику разработки без проектов.
Но это только на первый взгляд. В действительности я не использую терминологию Django, в которой проект - это продукт действия django-admin.py startproject, порождающий дополнительную ветвь в иерархии и приводящий к повсеместному использованию projectname. в питон коде. Для меня проект - это скорее объединение приложений, как reusable (как-то django-tagging, django-mptt и многие многие другие) с одной стороны, так и тех, которые разрабатываются исключительно для текущего веб-сайта, под одной общей крышей (settings.py, urls.py).
В идеале архитектура любого моего проекта выглядит как:
project/
application/
another_application/
locale/
templates/
settings.py
urls.py
Т.е. по-большому счету ничего лишнего. Управление и деплоймент проекта ведется при помощи универсальной утилиты
django-admin.py, которой передаются переменные DJANGO_SETTINGS_MODULE (settings) и PYTHONPATH (абсолютный путь к project/) (опять же в идеале создаются алиасы для каждого из проекта вида django-project и это в дальнейшем облегчает их использование в коммандной строке).
И казалось бы жизнь прекрасна и чудесна. Но так было до сегодняшнего дня, а сегодня я решил установить django-compress - приложение для сжатие CSS и JavaScript файлов. И одним из условий его использования было выполнение комманды
$ ./manage.py synccompress
Я, конечно, ничуть не смутился и попытался было:
$ django-project synccompress
но эта попытка закончилась
Unknown command: 'synccompress'
Type 'django-admin.py help' for usage.
Причина оказалось простой и, наверное, вполне логичной. django-admin.py вызывает django.core.management.execute_from_command_line, manage.py же, лежащий в директории проекта, после его создания (startproject), вызывает django.core.management.execute_manager. Вся же разница состоит в том, какая утилита управления (ManagementUtility) инициализируется и выполняется в этих функциях. И в итоге, ProjectManagementUtility считывает дополнительные команды, которые находятся в директории commands всех приложений, перечисленных в INSTALLED_APPS проекта. Именно это и дает возможность выполнения кастомных команд.
Собственно все это и навело на мысль создания "магичной" (новый тренд в джанго-среде) утилиты django-manage.py. Программный код этого велосипеда:
Установка выполняется копированием сохраненного кода в PATH и выдачей ему прав на исполнение (последнее только для Unix'ов).
Примеры использования тоже вполне очевидны:
$ cd /path/to/project
$ django-manage.py help
django-manage.py [options] [args]
Django command line tool, version 0.97-pre-SVN-unknown
Type 'django-manage.py help ' for help on a specific subcommand.
Available subcommands:
adminindex
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
reset
runfcgi
runserver
shell
sql
sqlall
sqlclear
sqlcustom
sqlflush
sqlindexes
sqlinitialdata
sqlreset
sqlsequencereset
startapp
synccompress
syncdb
test
testserver
validate
Ну и подитоживая могу лишь порадоваться, что процесс расширения Django под свои нужды проходит так просто и безболезненно.
Важно! Сей метод подходит лишь для архитектуры, описанной мной в начале поста, если вы используете архитектуру Django-проектов используйте для этих же целей manage.py, расположенный в корне директории проекта.
UPD 1 Добавлена проверка текущей рабочей директории для Windows, так как в нем нет ключа PWD в словаре os.environ.
UPD 2 Добавлена поддержка settings, project.settings (стандартной архитектуры проектов Django).