3 июля 2010 г.

musicmans.ru | Как сделать сайт на Django | Cтруктура проекта

Структура проекта может быть по вашему вкусу. Тут нет каких-то жестких правил, хотя правила в создании django приложений (не проекта) все-таки есть. Итак, приведем в пример структуру pinax сайта проекта:
  1. apps  
  2. deploy  
  3. media  
  4. site_media  
  5. templates  
  6. tests  
  7.   
  8. __init__.py  
  9. context_processors.py  
  10. manage.py  
  11. urls.py  
  12. settings.py  

Мы подсмотрим у профессионалов, virtualenv мы использовать не будем, поэтому немного подсократим:

PROJECT_ROOT/
|-- apps/ # Django приложения сайта
|-- etcs/ # Разные конфигурационные файлы
|-- settings/ # Настройки
|-- templates/ # темплейты для всего сайта
|-- __init__.py # Инициализация пакета python
|-- requirements.txt #файл формата pip со списком приложений для сайта
|-- manage.py # файл запуска\управления проекта
`-- urls.py # Главный URLconf

Разделение setting для разработки и развертывания одна из постоянно обсуждаемых вещей в django мире. Начнем с того, что разделим общие настройки и настройки развертывания плюс добавим несколько своих директорий.

|-- PROJECT_ROOT/
| |-- apps/
| |-- etc/
| |-- settings/
| | |-- __init__.py
| | |-- common.py
| | |-- development.py
| | `-- production.py
| |-- templates/
| |-- __init__.py
| |-- manage.py
| `-- urls.py
|-- www/
| |-- media/
| | |-- static/
|-- develop/

Статику (изображения, css, яваскрипт), которую веб сервер будет отдавать напрямую, мы вынесем за пределы PROJECT_ROOT.

Общие настройки определим в модуле settings.common. В development и production будут находиться специфичные настройки, а также они будут импортровать common, а manage.py будет загружать development.py, а в случае его отсутствия (svn:ignore) - production.py.

У меня получилась следующая структура проекта:



Обратите внимание на директорию develop, там будут лежать вещи, которые относятся к разработке, например отправим туда файл конфигурации development.py, вдруг кому-нибудь придется развертывать проект для разработки, тогда он легко сможет взять файл оттуда. Также обратите внимание на файл develompent.py в самом проекте, декоратор иконок subversive говорит нам о том, что он находится в svn:ignore.

Итак, переместим settings.py в common.py.

Подредактируем файлы примерно следующим образом (вывожу только то, что изменилось):

common.py:
  1. # -*- mode: python; coding: utf-8; -*-  
  2. ''''' 
  3. Created on 02.07.2010 
  4. '''  
  5. import os  
  6. import sys  
  7.   
  8. ADMINS = (  
  9.     ('Vermus''admin@musicmans.ru'),  
  10. )  
  11.   
  12. MANAGERS = ADMINS  
  13.   
  14. TIME_ZONE = 'Europe/Moscow'  
  15.   
  16. LANGUAGE_CODE = 'ru-RU'  
  17.   
  18. #Определяем корень проекта  
  19. PROJECT_ROOT = os.path.normpath(os.path.dirname(os.path.dirname(__file__)))  
  20.   
  21. #Добавляем apps в системную переменную path  
  22. sys.path.insert(0, os.path.join(PROJECT_ROOT, 'apps'))  
  23.   
  24. #URL к медиа файлам  
  25. MEDIA_URL = '/media/'  
  26. #путь в системе к медиа файлам  
  27. MEDIA_ROOT = os.path.join(os.path.dirname(PROJECT_ROOT), os.path.join('www', MEDIA_URL.strip('/') ))  
  28.   
  29. #URL к статическим файлам  
  30. STATIC_URL = MEDIA_URL + 'static/'  
  31. #пусть в системе к статическим файлам  
  32. STATIC_ROOT = os.path.join(MEDIA_ROOT, 'static')   
  33.   
  34. ROOT_URLCONF = 'urls'  
  35.   
  36. #Админка нам не нужна, убираем  
  37. #ADMIN_MEDIA_PREFIX = '/media/'  
  38.   
  39. TEMPLATE_DIRS = (  
  40.     os.path.join(PROJECT_ROOT, 'templates'),  
  41. )  

development.py (svn:ignore):
  1. # -*- mode: python; coding: utf-8; -*-  
  2.   
  3. from common import *  
  4.   
  5. DEBUG = True  
  6. TEMPLATE_DEBUG = DEBUG  
  7.   
  8. DATABASES = {  
  9.     'default': {  
  10.         'ENGINE''django.db.backends.postgresql_psycopg2'# Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.  
  11.         'NAME''musicmans'# Or path to database file if using sqlite3.  
  12.         'USER''user'# Not used with sqlite3.  
  13.         'PASSWORD''pass'# Not used with sqlite3.  
  14.         'HOST''localhost'# Set to empty string for localhost. Not used with sqlite3.  
  15.         'PORT'''# Set to empty string for default. Not used with sqlite3.  
  16.     }  
  17. }  

production.py:
  1. # -*- mode: python; coding: utf-8; -*-  
  2.   
  3. from common import *  
  4.   
  5. DEBUG = False  
  6.   
  7. DATABASES = {  
  8.     'default': {  
  9.         'ENGINE''django.db.backends.postgresql_psycopg2'# Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.  
  10.         'NAME''musicmans'# Or path to database file if using sqlite3.  
  11.         'USER''user'# Not used with sqlite3.  
  12.         'PASSWORD''pass'# Not used with sqlite3.  
  13.         'HOST''localhost'# Set to empty string for localhost. Not used with sqlite3.  
  14.         'PORT'''# Set to empty string for default. Not used with sqlite3.  
  15.     }  
  16. }  

Итак, единственное, что пока отличает production от develompent, переменная DEBUG и настройки базы данных (для нашего случая можно установить один пароль, и они тоже не будут отличаться, можно переместить в common.py). Остальное мы постарались сделать независимым от платформы и месторасположения проекта в системе.

Отключим в eclipse Window -> Preferences => Pydev -> Editor -> Code Analysis unused wild import, иначе будем получать много предупреждений от Code Analysis (в связи с нашими import *).

Отредактируем manage.py (в его начале мы разбираемся с settings проекта, потом настраиваем eclipse для отладки django проекта):
  1. #!/usr/bin/env python  
  2. import sys  
  3.   
  4. from django.core.management import execute_manager  
  5.   
  6. try:  
  7.     import settings.development as settings  
  8. except ImportError:  
  9.     try:  
  10.         import settings.production as settings  
  11.     except:  
  12.         sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)  
  13.         sys.exit(1)  
  14.   
  15. if __name__ == "__main__":  
  16.     if len(sys.argv) > 1:  
  17.         command = sys.argv[1]  
  18.     if settings.DEBUG and (command == "runserver" or command == "testserver"):  
  19.         # Make pydev debugger works for auto reload.  
  20.         try:  
  21.             import pydevd  
  22.         except ImportError:  
  23.             sys.stderr.write("Error: " +  
  24.                 "You must add org.python.pydev.debug.pysrc to your PYTHONPATH.")  
  25.             sys.exit(1)  
  26.      
  27.         from django.utils import autoreload  
  28.         m = autoreload.main  
  29.         def main(main_func, args=None, kwargs=None):  
  30.             import os  
  31.             if os.environ.get("RUN_MAIN") == "true":  
  32.                 def pydevdDecorator(func):  
  33.                     def wrap(*args, **kws):  
  34.                         pydevd.settrace(suspend=False)  
  35.                         return func(*args, **kws)  
  36.                     return wrap  
  37.                 main_func = pydevdDecorator(main_func)  
  38.       
  39.             return m(main_func, args, kwargs)  
  40.       
  41.         autoreload.main = main  
  42.       
  43.     execute_manager(settings)  

Выполняем все действия по вышеприведенной ссылке, чтобы запустить отладку проекта. Кстати, в новом pydev появился конфигуратор отладчика для django:



Но он многого не дает, как я понял, единственное --no-reload прописан по умолчанию и в аргументах можно просто указать runserver.

Итак, запускаем отладку:



И заходим браузером по адресу http://127.0.0.1:8000/, и видим классику:

7 комментариев:

  1. Я бы посоветовал

    from common import *

    перенести в начало файлов dev.py и product.py.

    ОтветитьУдалить
  2. Использовать Python и не использовать virtualenv — это не правильно!

    ОтветитьУдалить
  3. > Я комментирует...
    > Я бы посоветовал

    Согласен. Материал по теме http://habrahabr.ru/blogs/python/76738/

    >bsdemon комментирует...
    >Использовать Python и не использовать virtualenv — это не правильно!

    Почему? Если окружение python на хосте предназначается для обслуживания одного проекта, для чего еще один костыль в систему? Убедите меня, я пока причин использовать virtualenv на VDS не вижу.

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

    ОтветитьУдалить
  5. В manage.py потерялся import sys, точнее, его надо делать вначале, иначе на if len(sys.argv) ошибка.

    ОтветитьУдалить
  6. Doctor013, действительно, у себя поменял, а тут забыл, спасибо.

    ОтветитьУдалить
  7. Извините, что опять обращаю внимание, натура такая :-) . Нестыковка.
    В структуре проекта -> www/media/static
    Картинка Эклипса -> www/static
    Судя по контексту правильный вариант - первый.

    ОтветитьУдалить