Python (ПИТОН) \ Руководство по Django

Руководство по Django Bazaar

Руководство по Django

Ваше первое Джанго-приложение, часть 1ая.

Ну шо? Давайте начнем изучать Джангу!

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

Оно будет состоять из 2х частей:

  • Пользовательский раздел сайта для просмотра опроса и голосования
  • Административный раздел для добавления, изменения и удаления опросов

Предположим что Джангу вы уже установили. Если она установлена, то комманда import django должна выполниться без ошибок.

Ё-моё, ничего не понимаю!

Если туториал вызывает у вас какие-то затруднения, отправляйте свои сообщения в группу django-users или #django на irc.freenode.net.

Cоздание проекта.

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

Из коммандной строки перейдите в директорию, в которой будет располагаться проект, затем выполните комманду django-admin.py startproject mysite. В текущей директории будет создана папка mysite.

Ахтунг!!!

Если вы используете Mac OS, при попытке выполнить комманду django-admin.py startproject mysite, может возниктнуть сообщение "permission denied"(отсутствие прав доступа). В Unix-подобных системах файл django-admin.py должен быть исполняемым (помечен как "executable"), только после этого он может быть запущен как программа.

Ахтунг!!!

Имя пректа не должно совпадать со встроенными в Питон или Джанго компонентами. Не называйте ваш проект django или python - могут возникнуть конфликты.

(django-admin.py должен быть прописан в путях. Если в путях его нет, то при его вызове нужно указать полный путь, например C:/python/site-packages/django/bin/django-admin.py startproject mysite)

Ахтунг!!!

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

Коммандой startproject будут созданы следующие файлы:

mysite/
    __init__.py
    manage.py
    settings.py
    urls.py

Вот что значат эти файлы:

  • __init__.py: Пустой файл, уведомляющий Питон о том, что данную директорию следует расмматривать как питоновский пакет.
  • manage.py: Утилита, позволяющая работать с Джпнго-проектом из коммандной строки.
  • settings.py: Настройки/конфигурация Джанго-проекта
  • urls.py: Описание URL-ов Джнаго-проекта; "таблица содержимого" Джанго-ориетированного сайта.

Отладочный сервер.

Убедимся что наш проект работает. Зайдем в директорию mysite и выполним комманду python manage.py runserver.В коммандной строке вы должны увидеть следующее:

Validating models...
0 errors found.

Django version 0.95, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

Вы запустили отладочный сервер Джанго, целиком написанный на Питоне. Он включен в Джанго с целью избавить пользователя от настройки конечного сервера, например Apache.

Самое время ометить: НЕ ИСПОЛЬЗУЙТЕ этот сервер ни в чем похожем на конечную рабочую среду, он предназначен для использования только во время разработки.

Итак сервер запущен, зайдите на адрес http://127.0.0.1:8000/ из браузера. Вы увидите страницу "Welcome to Django" в приятных постельных тонах. Оно работает!!!

Ахтунг!!!

По умолчанию комманда startserver запускает отладочный сервер на 8000 порту. Если вы хотите поменять порт, передайте его в качестве аргумента в коммандной строке при запуске сервера. Например, следующая комманда запустит сервер на 8080 порту.
python manage.py runserver 8080
Вся документация по отладочному серверу находится вот здесь.

Настройка базы данных

Сейчас отредактируем файл settings.py. Это обычный питоновский модуль, объявленные в нем переменные отвечают за различные настройки Джанго. Приведите эти настройки в соответсвие с параметрами соединения вашей базы данных.

  • DATABASE_ENGINE - Может принимать одно из следующих значений 'postgresql_psycopg2', 'mysql' или 'sqlite3'. Доступны и другие СУБД.
  • DATABASE_NAME - Имя базы данных, или полный путь к файлу БД для SQLite.
  • DATABASE_USER - Имя пользователя БД (не используется в SQLite).
  • DATABASE_PASSWORD - Пароль к БД (не используется в SQLite).
  • DATABASE_HOST - Хост на котором располагается БД. Оставьте эту строку пустой, если сервер и БД располагаются на одной и той же машине (не используется в SQLite).
Ахтунг!!!

Если вы используете PostgreSQL или MySQL убедитесь что БД с такими настройками уже создана. Создать БД можно запросом "CREATE DATABASE database_name;" в консольном менеджере вашей СУБД.

Во время редактирования settings.py обратите внимание на перемнную INSTALLED_APPS, расположенную в конце файла. В ней содержатся имена всех Джанго-приложений, включенных в текущий Джанго-проект. Приложения могут использоваться в нескольких проектах.

По умолчанию INSTALLED_APPS содержит следующие Джанго-приложения:

  • django.contrib.auth - Система авторизации.
  • django.contrib.contenttypes - Система управления контентом.
  • django.contrib.sessions - Система управления сессиями.
  • django.contrib.sites - Система управления несколькими сайтами на одном Джанго-проекте.

Эти приложения включены по умолчанию, поскольку могут использоваться в самом общем случае.

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

python manage.py syncdb
Ахтунг!!!

После выполнения этой комманды у меня вылетело сообщение следующего содержания:
G:\project\python\django\mysite>python manage.py syncdb

Traceback (most recent call last):
  File "manage.py", line 11, in ?
    execute_manager(settings)
  File "c:\python24\Lib\site-packages\django\core\management.py", line 1672, in execute_manager
    execute_from_command_line(action_mapping, argv)
  File "c:\python24\Lib\site-packages\django\core\management.py", line 1571, in execute_from_command_line
    action_mapping[action](int(options.verbosity), options.interactive)
  File "c:\python24\Lib\site-packages\django\core\management.py", line 504, in syncdb
    cursor = connection.cursor()
  File "c:\python24\lib\site-packages\django\db\backends\postgresql_psycopg2\base.py", line 54, in cursor
    postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')]
ValueError: invalid literal for int(): 0,

Избавился я от этой ошибки, изменив строку 54 в файле C:\Python24\Lib\site-packages\django\db\backends\postgresql_psycopg2\base.py с

postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')]
на
import re
...
postgres_version = [int(re.sub("[^0-9]", "", val)) for val in cursor.fetchone()[0].split()[1].split('.')]
А потом подумал.... и поставил последнюю версию Джанги с SVN.

Комманда syncdb просматривает INSTALLED_APPS и создает необходимое количество таблиц в БД. Сообщения о вновь созданных таблицах будут выведены в консоль, так же вам будет предложено создать мегапользователя для системы авторизации. Давайте, сделайте это.

Если вам интересно, запустите консольный менеджер вашей БД и введите \dt (PostgreSQL), SHOW TABLES; (MySQL), или .schema (SQLite) для отображения созданных Джангой таблиц.

Для минималистов

Как сказано выше, по умолчанию в проект включено несколько приложений, но некоторые из них могут оказываются ненужными. Если какие-то приложения вам не нужны вы можете их закомментировать или удалить из INSTALLED_APPS до выполения syncdb. Комманда syncdb создаст таблицы только для приложений содержащихся в INSTALLED_APPS.

Создание моделей

Сейчас ваш проект настроен и подгтовлен к началу работы.

Каждое написанное на Джанге приложение, состоит из модулей, расположенных в некоторых директориях, прописанных в питоновских путях. Джанго поставляется с утилитой, которая автоматически генерирует базовую структуру директорий приложения.

Отличия между проектом и приложением

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

В директории mysite мы создадим приложение для подстчета голосов. В последствии, приложение будет связано с проектом и обращаться к нему можно будет как к пакету mysite.polls. Позже мы обсудим как сделать Джанго приложение самостоятельным пакетом.

Убедившись что вы находитесь в директории mysite, создайте приложение коммандой:

python manage.py startapp polls

Она создаст директорию pools, содержащюю следующие файлы:

polls/
    __init__.py
    models.py
    views.py

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

Первый шаг при создании Джанго-веб-приложения с базой данных это описание моделей - фактически разметка базы данных с использованием метаданных.

Философия

Модель - это отдельный определенный источник данных о ваших данных, описывающий поля таблицы БД и информацию о поведении сохраненных данных. Джанго следует принципу DRY(Dont Repeat Yourself). Его суть - однократное определение модели(в одном месте) и многократное использование этой структуры данных без дублирования кода.

В нашем приложении создадим две модели poll(опрос) и choice(вариант ответа). Опрос содержит вопрос и дату публикации. Вариант содержит ответ и количество голосов. Каждый вариант связан с опросом.

Модель реализуется в виде обыкновенного питоновского класса. Вставьте в файл polls/models.py следующий код:

from django.db import models
class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    choice = models.CharField(max_length=200)
    votes = models.IntegerField()
Недопустимый аргуент max_length

Если Джанго выдает сообщение о том что функция не имеет аргумента max_length, значит скорее всего вы используете старую версию Джанги (это руководство написано для последней версии Джанги). Если вы хотите запустить этот пример на предыдущих версиях Джанги, вам следует переключиться на руководство по Джанге 0.96, поскольку здесь содержится описание некоторых возможностей присущих только последней версии и неподдерживаемых предыдущими.

Пройдемся по коду. Каждая модель является классом, наследуемым от django.db.models.Model.

Каждому атрибуту экземпляра класса модели, поставлено в соотвествие поле(столбец) в БД. Тип данных хранимых в этом поле, определяется классом models.*Field, например, models.CharField - символьное поле, models.DateTimeField - поле для записи даты.

В инструктор models.*Field может быть передан необязателный первый аргумент, содержащий детальное описание поля. Если этого аргумента нет, описание будет сгенерировано автоматически из имени атрибута модели(имени поля БД).

Конструкторы полей могут принимать и другие аргументы. Например, при создании поля типа CharField требуется указать значение аргумента max_length. Это значение используется не только при описании структуры данных, но и при их проверке, в чем мы чуть позже убедимся.

В заключение отметим что связь между моделями осуществляется посредством внешнего ключа models.Foreign. Джанго поддерживает такие отношения между данными как один ко многим, многие ко многим и один к одному.

Активация моделей

Сравнительно небольшой код модели дает Джанге достаточно много информации. На основании которой Джанго сможет сделать следующее:

  • Создать структуру базы данных (операторы CREATE TABLE)
  • Создать набор API функции для взаимодействия между БД и объектами Poll и Choice

Прежде всего мы должны сообщить нашему проекту о том, что собираемся использовать в нем приложение pools. Для этого в файле settings.py в переменную INSTALLED_APPS следует добавить строку 'mysite.polls'. Должно получиться вот так:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'mysite.polls'
)

Сейчас проект mysite "знает" о том что в его включено приложение pools. Теперь вы можете выполнить следующую комманду:

python manage.py sql polls

На экран будет выведена следующая информация (операторы CREATE TABLE SQL для приложения polls):

BEGIN;
CREATE TABLE "polls_poll" (
    "id" serial NOT NULL PRIMARY KEY,
    "question" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "poll_id" integer NOT NULL REFERENCES "polls_poll" ("id"),
    "choice" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
COMMIT;

Следует отметить:

  • Выведенная информация зависит от того какую БД вы используете
  • Имена таблиц генерируются автоматически и получаются путем соединения имени приложения (polls) и имени модели(poll и choice) (можно переопределить)
  • Первичные ключи (IDs) добавляются автоматически (можно переопределить)
  • К имени поля внешенего ключа добавляется "_id" (можно переопределить)
  • Связь внешнего ключа явно задается оператором REFERENCES
  • В зависимости от используемой БД для поля "id" будет установлен один из следующих типов: auto_increment (MySQL), serial (PostgreSQL), или integer primary key (SQLite)
  • Комманда sql не выполняет sql-код в БД, а лишь выводит на экран то, что Джанга намеривается сделать в БД. Если хотите можете скопировать полученный код и запустить его в коммандной сроке вашей БД. Джанга позволяет выполнить полученный sql-код более простым способом, в чем мы чуть позже сможем убедиться.
Если вам интересно, то можете попробовать выполнить следующие комманды:
  • python manage.py validate - Проверяет вашу модель на наличие в ней ошибок.
  • python manage.py sqlcustom polls - Выводит специальные операторы SQL (такие как модификаторы таблиц и ограничения), определенные в приложении.
  • python manage.py sqlclear polls - Выводит комманды DROP TABLE, для уже существующих в БД таблиц.
  • python manage.py sqlindexes polls - Выводит все операторы CREATE INDEX для данного приложения.
  • python manage.py sqlall polls - Поочередно выполняет комманды sql, sqlcustom, и sqlindexes.

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

Выполните комманду syncdb для создания в БД таблиц, соответстущих созданным моделям:

python manage.py syncdb

Комманда syncdb выполняет sql-код, генерируемый коммандой sqlall для всех приложений, содержащихся в INSTALLED_APPS и еще не существующих в БД. Она создает все таблицы, индексы и начальные данные для приложений, добавленных в проект после предыдущего выполнения комманды syncdb. Комманда syncdb может быть выполнена любое количество раз, поскольку создает только несуществующие в БД таблицы.

Более подробную информацию об утилите manage.py вы можете найти здесь.

Поиграемся с API

Сейчас мы откроем интерактивный интерпритатор Питона и поиграемся с API предоставляемым Джангой. Для вызова интерпритатора Питона достаточно выполнить следющую комманду:

python manage.py shell

Мы используем эту комманду вместо прстого вызова "python", поскольку manage.py устанавливает окружение проекта для вас. Установка среды поекта включает слудующие вещи:

  • Добавление mysite в sys.path. Поскольку в Джанго часто приходиться испольовать ссылки на определенные части проекта в виде принятого в Питоне указания пути к модулю в виде разделенных точками промежуточных ссылок (например, 'mysite.polls.models'). Для корректной работы пакет mysite должен быть добавлен в Питоновские пути, за которые отвечает перемнная sys.path.

    Все ссылки на пакеты, содержащиеся в переменной INSTALLED_APPS, имеют такой формат записи.

  • Устанавливает переменную окружения DJANGO_SETTINGS_MODULE, сообщающую Джанге путь к файлу settings.py.
Как обойтись без manage.py

Вы не хотите использовать manage.py? Нет проблем. Вам лишь следует убедиться в том, что вы находитесь в директории, содержащей mysite (при этом комманда import mysite должна работать) и присвоить переменной окружения DJANGO_SETTINGS_MODULE путь к файлу конфигурации mysite.settings.

Более подробную информацию вы можете найти здесь.

Итак сейчас у вас запущен интерактивный интерпритатор Питона. Давайте поэксперементируем с API Джанги.

#Импортируем только что написанные нами классы моделей.
>>> from mysite.polls.models import Poll, Choice

# Пока что у нас не создано ни одного опроса.
>>> Poll.objects.all()
[]

# Создаем новый опрос.
>>> import datetime
>>> p = Poll(question="What's up?", pub_date=datetime.datetime.now())

# Используя метод save(), сохраняем обект в БД.
>>> p.save()

# Объету будет присвоен определенный ID. В зависимости от того какую БД вы используете на экран 
# может быть выведено "1L" вместо "1". В принципе это не важно, поскольку это означаеть лишь то, что 
# используемый БД тип целого числа совпадает с Питоновским динным целым (long int).
>>> p.id
1

# Доступ к полю БД осуществляется как к обыкновенному свойству объекта.
>>> p.question
"What's up?"
>>> p.pub_date
datetime.datetime(2007, 7, 15, 12, 00, 53)

# После изменения значения свойства, вызовем метод save().
>>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0)
>>> p.save()

# Метод objects.all() выведет на экран список всех опросов содержащихся в БД.
>>> Poll.objects.all()
[<Poll: Poll object>]

<Poll: Poll object> - достаточно бесполезное представление созданного нами объекта. Давайте внесем некоторые изменения в модель опроса (в файл polls/models.py), а именно добавим в классы Poll и Choice метод __unicode__().

class Poll(models.Model):
    # ...
    def __unicode__(self):
        return self.question

class Choice(models.Model):
    # ...
    def __unicode__(self):
        return self.choice
Если __unicode__() не работает

Если после добавления в модель метода __unicode__() в представлении обекта модели ничего не изменилось, значит вы ипользуюете старую версию Джанги.

Если вы хотите использовать старую версию джанги, вам следует переключится на руководство по Джанге 0.96, поскольку данное руководство предназначено для текущей (находящейся в данный момент в активной разработке) версии Джанги и содержит некоторые особенности присущие только ей.

Метод __unicode__() не только облегчает работу с Джангой из коммандной строки, но и используется Джангой при автоматической генерации администраторской части.

Почему __unicode__(), а не __str__()?

Если вы знакомы с Питоном, то скорее всего вы привыкли добавлять в классы метод __str__(), а не __unicode__(). Здесь мы используем __unicode__() поскольку модели в Джанго по умолчанию используют Юникод. Все данные, сохраняемые в БД, преобразуются в Юникод.

Модели по умолчанию имеют метод __str__(), при вызове которого вызывается метод __unicode__(), преобразующий возвращаемые данные байтовую строку в кодировке UTF-8. Это значит, что unicode(p) возвратит Юникод строку, а str(p) - обычную строку, символы которой закодированы в UTF-8.

Если все вышесказанное вам не понятно, просто добавьте метод __unicode__() в ваши модели.

Теперь добавим в модель некоторый метод (чисто для примера).

import datetime
# ...
class Poll(models.Model):
    # ...
    def was_published_today(self):
        return self.pub_date.date() == datetime.date.today()

Инструкция import datetime импортирует стандартный Питоновскый модуль datetime.

Выполнив комманду python manage.py shell, перейдем обратно в интерактивный интерпритатор Питона:

>>> from mysite.polls.models import Poll, Choice

# Убедимся, что добавленный нами метод __unicode__() работает.
>>> Poll.objects.all()
[<Poll: What's up?>]

# Джанго предоставляет мощный механизм API функций поиска в БД по ключевым аргументам.
>>> Poll.objects.filter(id=1)
[<Poll: What's up?>]
>>> Poll.objects.filter(question__startswith='What')
[<Poll: What's up?>]

# Получим опрос, созданный в 2008 году. Если сейчас другой год, вам следует изменить его 
# соответсвующим образом и в функции запроса.
>>> Poll.objects.get(pub_date__year=2008)
<Poll: What's up?>

>>> Poll.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Poll matching query does not exist.

# В Джанго также реализован механизм поиска по первичному ключу
# Следующий код аналогичен Poll.objects.get(id=1).
>>> Poll.objects.get(pk=1)
<Poll: What's up?>

# Убедимся, что добавленный нами в класс модели метод работает.
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_today()
False

# Для нашего опроса (Poll) создадим два варианта ответа (Choice). Методом create 
# создается новый объект представляющий варианта ответа, затем выполняется комманда INSERT, 
# добавляющая в БД информацию об обекте. Метод create возвращает ссылку на созданный обект.
>>> p = Poll.objects.get(pk=1)
>>> p.choice_set.create(choice='Not much', votes=0)
<Choice: Not much>
>>> p.choice_set.create(choice='The sky', votes=0)
<Choice: The sky>
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)

# Объект Choice имеет API для доступа к связанным с ним обектам типа Poll.
>>> c.poll
<Poll: What's up?>

# И наоборот: объект Poll имеет доступ обектам типа Choice.
>>> p.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> p.choice_set.count()
3
# API Джанги предоставляет возможность обратиться к информации любого уровня вложенности.
# Двойной подчерк используется для разделения уровней вложенности (для формирования пути к 
# нужной вам информации).
# Найдем все варианты ответов для всех опросов, опубликованных в 2008 году.
>>> Choice.objects.filter(poll__pub_date__year=2008)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]

# Давайте удалим какой-нибуть из вариантов ответа. Для этого используем функцию delete().
>>> c = p.choice_set.filter(choice__startswith='Just hacking')
>>> c.delete()

Более подробную информации об API БД можно найти здесь.

После знакомства с API, переходите к изучению второй части руководства, описывающей процесс создания системы администрирования сайта.

Южно-Уральский Госудаственный Университет. ПС. АиУ.
Написать нам письмо
  Написать нам письмо