3 июля 2010 г.

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

Структура проекта может быть по вашему вкусу. Тут нет каких-то жестких правил, хотя правила в создании django приложений (не проекта) все-таки есть. Итак, приведем в пример структуру pinax сайта проекта:

apps
deploy
media
site_media
templates
tests

__init__.py
context_processors.py
manage.py
urls.py
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:

# -*- mode: python; coding: utf-8; -*-
'''
Created on 02.07.2010
'''
import os
import sys

ADMINS = (
('Vermus', 'admin@musicmans.ru'),
)

MANAGERS = ADMINS

TIME_ZONE = 'Europe/Moscow'

LANGUAGE_CODE = 'ru-RU'

#Определяем корень проекта
PROJECT_ROOT = os.path.normpath(os.path.dirname(os.path.dirname(__file__)))

#Добавляем apps в системную переменную path
sys.path.insert(0, os.path.join(PROJECT_ROOT, 'apps'))

#URL к медиа файлам
MEDIA_URL = '/media/'
#путь в системе к медиа файлам
MEDIA_ROOT = os.path.join(os.path.dirname(PROJECT_ROOT), os.path.join('www', MEDIA_URL.strip('/') ))

#URL к статическим файлам
STATIC_URL = MEDIA_URL + 'static/'
#пусть в системе к статическим файлам
STATIC_ROOT = os.path.join(MEDIA_ROOT, 'static')

ROOT_URLCONF = 'urls'

#Админка нам не нужна, убираем
#ADMIN_MEDIA_PREFIX = '/media/'

TEMPLATE_DIRS = (
os.path.join(PROJECT_ROOT, 'templates'),
)

development.py (svn:ignore):

# -*- mode: python; coding: utf-8; -*-

from common import *

DEBUG = True
TEMPLATE_DEBUG = DEBUG

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'musicmans', # Or path to database file if using sqlite3.
'USER': 'user', # Not used with sqlite3.
'PASSWORD': 'pass', # Not used with sqlite3.
'HOST': 'localhost', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
}

production.py:

# -*- mode: python; coding: utf-8; -*-

from common import *

DEBUG = False

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'musicmans', # Or path to database file if using sqlite3.
'USER': 'user', # Not used with sqlite3.
'PASSWORD': 'pass', # Not used with sqlite3.
'HOST': 'localhost', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
}

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

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

Отредактируем manage.py (в его начале мы разбираемся с settings проекта, потом настраиваем eclipse для отладки django проекта):

#!/usr/bin/env python
import sys

from django.core.management import execute_manager

try:
import settings.development as settings
except ImportError:
try:
import settings.production as settings
except:
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__)
sys.exit(1)

if __name__ == "__main__":
if len(sys.argv) > 1:
command = sys.argv[1]
if settings.DEBUG and (command == "runserver" or command == "testserver"):
# Make pydev debugger works for auto reload.
try:
import pydevd
except ImportError:
sys.stderr.write("Error: " +
"You must add org.python.pydev.debug.pysrc to your PYTHONPATH.")
sys.exit(1)

from django.utils import autoreload
m = autoreload.main
def main(main_func, args=None, kwargs=None):
import os
if os.environ.get("RUN_MAIN") == "true":
def pydevdDecorator(func):
def wrap(*args, **kws):
pydevd.settrace(suspend=False)
return func(*args, **kws)
return wrap
main_func = pydevdDecorator(main_func)

return m(main_func, args, kwargs)

autoreload.main = main

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
    Судя по контексту правильный вариант - первый.

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