Среды Web-разработки на языке Python, Часть 1

Company Site: {% block title %}Page{% endblock %}Company Site: {% block title %}Page{% endblock %}
Разработка для Web с помощью Django и Python

Среда Web-разработки Django на языке Python, от установки до законченного Web-сайта

Содержание

Уровень сложности: средний
Источник: IBM developerWorks

Йен Маурер, Senior Consultant, Brulant, Inc.

В этой первой статье из двух, мы представим вам Django - среду с открытым исходным кодом для ведения разработки Web-приложений в стиле модель-вид-контроллер (model-view-controller - MVC), вооруженную мощью языка Python. С помощью Django вы можете в считанные минуты создавать высококачественные, легкоуправляемые Web-приложения, работающие под управлением баз данных.

Проект Django представляет собой настраиваемую пользователем среду разработки. Он берёт начало из Web-сайта одной онлайн-газеты и был выпущен как система с открытым исходным кодом в июле 2005 года. Главные компоненты среды разработки Django следующие:

  • Объектно-реляционное отображение (object-relational mapping) для создания моделей
  • Безупречный интерфейс администратора, специально созданный для конечных пользователей
  • Элегантно спроектированный механизм адресования (URL)
  • Язык шаблонов, для дизайнеров
  • Система кэширования

Эта статья - первая из двух статей о среде Web-разработки на языке Python. Вторая статья представит вам среду разработки TurboGears.

Чтобы использовать и понимать код в данной статье, вам необходимо установить Python и знать, как им пользоваться на начальном уровне. Проверьте, есть ли у вас Python, и какой версии, набрав python -V. Минимальным требованием Django является версия 2.3.5, которая доступна вам на Web-сайте Python (см. ссылку в разделе Ресурсы в конце статьи). Вам также следует хотя бы немного быть знакомым с архитектурой MVC.

Установка Django

В этой статье используется разрабатываемая версия Django для того, чтобы воспользоваться преимуществами последних улучшений, внесённых в среду разработки Django. Я рекомендую вам использовать эту версию до появления версии 0.95. Узнайте о наличии последней версии Django на его Web-сайте (снова см. ссылку в Ресурсах).

Чтобы скачать и установить Django вам нужно:
Листинг 1. Скачивание и установка Django

~/downloads# svn co http://code.djangoproject.com/svn/django/trunk/ django_src ~/downloads# cd django_src ~/downloads# python setup.py install

Инструмент администрирования Django

После установки Django вам необходим инструмент администрирования Django, а именно django-admin.py, добавленный в переменную окружения path. Листинг 2 показывает некоторые из команд, доступных инструменту администратора:
Листинг 2. Использование инструмента администрирования Django

~/dev$ django-admin.py usage: django-admin.py action [options] actions: adminindex [modelmodule ...] Prints the admin-index template snippet for the given model module name(s). ... snip ... startapp [appname] Creates a Django app directory structure for the given app name in the current directory. startproject [projectname] Creates a Django project directory structure for the given project name in the current directory. validate Validates all installed models. options: -h, --help show this help message and exit --settings=SETTINGS Python path to settings module, e.g. "myproject.settings.main". If this isn't provided, the DJANGO_SETTINGS_MODULE environment variable will be used. --pythonpath=PYTHONPATH Lets you manually add a directory the Python path, e.g. "/home/djangoprojects/myproject".

Проекты и приложения в Django

Чтобы начать проект Django, используйте команду программы django-admin startproject вот так:
Листинг 3.Создание проекта

~/dev$ django-admin.py startproject djproject

Показанная выше команда создает директорию под названием djproject, которая содержит файлы базовой конфигурации, необходимые для работы проекта Django:
Листинг 4. Содержание директории djproject

__init__.py manage.py settings.py urls.py

В этом проекте вы создадите приложение для отдела занятости, называемое "jobs." Для создания приложения используйте скрипт manage.py, который является специальным для проекта скриптом в django-admin.py, в котором автоматически задаётся файл settings.py:
Листинг 5. Использование manage.py с параметром startapp

~/dev$ cd djproject ~/dev/djproject$ python manage.py startapp jobs

Это создает костяк приложения с одним модулем Python для ваших моделей и другим для ваших видов (view). Директория jobs будет содаржать следующие файлы:
Листинг 6. Содержание директории приложения jobs

__init__.py models.py views.py

Местоположение приложения внутри проекта является чистой условностью, созданной для новых разработчиков в Django, а не требованием. Как только вы начнете перемешивать и сопоставлять приложения в нескольких проектах, вы можете поместить приложения в их собственные пространства имён для модулей и связать их вместе, используя настройки и главные файлы URL. Но пока, следуйте приведенным ниже этапам.

Чтобы Django знал о новом приложении, вам необходимо добавить строку в поле INSTALLED_APPS в файле settings.py. Для этого приложения для отдела занятости нужно добавить строку djproject.jobs:
Листинг 7. Добавление строки к settings.py

INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'djproject.jobs', )

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

У Django есть своя собственная библиотека object-relational mapper (ORM), которая поддерживает динамический доступ к базам данных через объектный интерфейс Python. Интерфейс Python является очень удобным и эффективным, но вы также можете отказаться от него и напрямую использовать SQL при необходимости.

На данный момент ORM предоставляет поддержку для баз данных PostgreSQL, MySQL, SQLite, а также Microsoft® SQL.

Это пример использует SQLite, в качестве интерфейса к базе данных. SQLite является легковесной базой данных, не требующей конфигурации и располагается на диске в виде простого файла. Чтобы использовать SQLite, просто установите библиотеку pysqlite с помощью инструментов установки (setuptools) (см. дополнительную информацию об инструментах установки (setuptools) и, в частности, об инструменте easy_install, который вам необходимо установить отдельно, в разделе Ресурсы):

easy_install pysqlite

Перед тем, как работать с моделью, сконфигурируйте базу данных в файле настроек. Для SQLite необходимо указывать только движок и имя базы данных.
Листинг 8. Конфигурирование базы данных в settings.py

DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = '/path/to/dev/djproject/database.db' DATABASE_USER = '' DATABASE_PASSWORD = '' DATABASE_HOST = '' DATABASE_PORT = ''

Это приложение для отдела занятости будет иметь два типа объектов: Местоположения (Locations) и Работы (Jobs). Местоположение включает в себя поля города, штата (по желанию), а также страны. Работа имеет местоположение, должность, описание и дату публикации.
Листинг 9. Модуль jobs/models.py

from django.db import models class Location(models.Model): city = models.CharField(maxlength=50) state = models.CharField(maxlength=50, null=True, blank=True) country = models.CharField(maxlength=50) def __str__(self): if self.state: return "%s, %s, %s" % (self.city, self.state, self.country) else: return "%s, %s" % (self.city, self.country) class Job(models.Model): pub_date = models.DateField() job_title = models.CharField(maxlength=50) job_description = models.TextField() location = models.ForeignKey(Location) def __str__(self): return "%s (%s)" % (self.job_title, self.location)

Метод __str__ - это специальный метод класса в языке Python, который возвращает строковое представление объекта. Django достаточно широко использует этот метод, когда отображает объекты в инструменте администратора.

Чтобы увидеть схему базы данных для модели, запустите manage.py с командой sql. Схема пока еще не будет задействована.
Листинг 10. Просмотр схемы базы данных с помощью команды manage.py sql

~/dev/djproject$ python manage.py sql jobs BEGIN; CREATE TABLE "jobs_job" ( "id" integer NOT NULL PRIMARY KEY, "pub_date" date NOT NULL, "job_title" varchar(50) NOT NULL, "job_description" text NOT NULL, "location_id" integer NOT NULL ); CREATE TABLE "jobs_location" ( "id" integer NOT NULL PRIMARY KEY, "city" varchar(50) NOT NULL, "state" varchar(50) NULL, "country" varchar(50) NOT NULL ); COMMIT;

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

~/dev/djproject$ python manage.py syncdb

Отметим, что команда syncdb просит вас создать учетную запись суперпользователя. Это происходит потому, что приложение django.contrib.auth, которое предоставляет базовые средства аутентификации пользователя, установлено по умолчанию в ваших настройках INSTALLED_APPS. Имя суперпользователя и пароль будут использоваться для регистрации в инструменте администратора, описанном в следующем разделе. Помните, что это имя и пароль суперпользователя Django, а не системы.

Наборы запросов

Модели Django обращаются к базе данных через изначально установленный Управляющий (Manager) класс, называемый objects. Например, чтобы вывести список всех Работ, вам нужно использовать метод all, принадлежащий менеджеру objects:
Листинг 11. Вывод всех работ (jobs)

>>> from jobs.models import Job >>> for job in Job.objects.all(): ... print job

Управляющий класс также имеет методы фильтрации, называемые filter (фильтрация) и exclude (исключение). Фильтрация получает все объекты, подходящие под условия, тогда как исключение дает все объекты, не подходящие под них. Нижеследующие запросы должны дать такие же результаты ("gte" означает "greater than or equal,"(больше или равно) и "lt" означает "less than")(меньше чем).
Листинг 12. Исключение и фильтрация работ (jobs)

>>> from jobs.models import Job >>> from datetime import datetime >>> q1 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1)) >>> q2 = Job.objects.exclude(pub_date__lt=datetime(2006, 1, 1))

Методы filter и exclude возвращают объекты QuerySet, которые можно связать в цепочку и которые могут даже представлять соединения. Запрос q4, приведенный ниже, будет находить работы, начиная с 1-го января 2006 года, в г. Кливленд (Cleveland), штат Огайо:
Листинг 13. Снова исключение и фильтрация работ (jobs)

>>> from jobs.models import Job >>> from datetime import datetime >>> q3 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1)) >>> q4 = q3.filter(location__city__exact="Cleveland", ... location__state__exact="Ohio")

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

Эта замедление в выполнении является очень практичной в сочетании с рассекающей (slicing) функциональностью языка Python. Вместо того, чтобы запрашивать все записи, а затем отсекать нужные записи, нижеследующий код использует смещение (OFFSET), равное 5, и предел (LIMIT), равный 10, в настоящем запросе SQL, весьма улучшая качество выполнения.
Листинг 14. Python-рассечение

>>> from jobs.models import Job >>> for job in Job.objects.all()[5:15] ... print job

Примечание: Используйте метод count, чтобы понять, сколько записей находятся в QuerySet. Метод len в Python делает полную оценку, а затем подсчитывает количество рядов, возращенных в виде записей, тогда как метод count делает действительный Подсчет (COUNT) SQL, который гораздо быстрее. И ваш администратор баз данных поблагодарит вас.
Листинг 15. Подсчет записей

>>> from jobs.models import Job >>> print "Count = ", Job.objects.count() # GOOD! >>> print "Count = ", len(Job.objects.all()) # BAD!

Для более подробной информации, см. раздел Ресурсы для ссылки на «Справочник по интерфейсу API базы данных» для Django.

Инструмент администратора

Одно из самых больших достоинств в Django - это отточенный интерфейс администратора. Этот инструмент был создан с учетом конечного пользователя, благодаря чему предоставляет вашим проектам отличное средство для ввода данных.

Инструмент администратора представляет собой приложение, которое идет вместе с Django. Перед тем, как его использовать, его необходимо установить так же, как и приложение jobs. Сперва нужно добавить модуль приложения (django.contrib.admin) в настройки INSTALLED_APPS:
Листинг 16. Изменения в settings.py

INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'djproject.jobs', 'django.contrib.admin', )

Чтобы сделать инструмент администратора доступным из адреса (URL) /admin, просто раскройте скобки комментария в строке, в предоставленном вам файле urls.py вашего проекта. В следующем разделе будет рассматриваться конфигурация URL более подробно.
Листинг 17. Использование urls.py, чтобы иструмент администратора стал доступным

from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^admin/', include('django.contrib.admin.urls.admin')), )

Пиложение администратора имеет свою модель базы данных, которую необходимо установить. Снова используйте команду syncdb, чтобы завершить следующее:

python manage.py syncdb

Чтобы увидеть инструмент администратора, вы можете использовать тест-сервер, которая прилагается к Django.
Листинг 18. Использование тест-сервера, чтобы увидеть инструмент администратора

~/dev/djproject$ python manage.py runserver Validating models... 0 errors found. Django version 0.95 (post-magic-removal), using settings 'djproject.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).

Теперь вы можете переместиться в инструмент администратора по адресу http://localhost:8000/admin и зарегистрироваться, используя данные администратора, созданные вами ранее. Вы заметите, что ни одна из ваших моделей не доступна для пользования.

Чтобы открыть доступ к классу через инструмент администратора, создайте для него подкласс Admin (Администратора). Затем вы можете настраивать то, как их можно администрировать добавлением характеристик классов к данному подклассу. Листинг 19 показывает, как добавлять класс Location (Местонахождения) к интсрументу администратора.
Листинг 19. Добасвление класса Location с помощью инструмента администратора

class Location(meta.Model): ... class Admin: list_display = ("city", "state", "country")

Теперь вы можете создавать, обновлять и удалять записи Местонахождения (Location) через интерфейс администратора.
Изменение местонахождений с помощью инструмента администратора



Вы можете выводить и сортировать Записи (Records) по городам, штатам и странам, в зависимости от характеристики класса list_display.
Вывод местонахождений с помощью инструмента администратора



Инструмент администратора имеет большое количество опций для управления каждым из классов моделей. Листинг 20 показывает несколько примеров, примененных к классу Job:
Листинг 20. Опции для управления классами моделей

class Job(meta.Model): ... class Admin: list_display = ("job_title", "location", "pub_date") ordering = ["-pub_date"] search_fields = ("job_title", "job_description") list_filter = ("location",)

В соответствие с вышеупомянутыми настройками, при выводе записей работ (job) будут использоваться: заголовок работы (job), местонахождения и дата издания. Работы будут располагаться в порядке даты издания, начиная с самого последнего (знак минус означает - в порядке убывания). Пользователи могут найти работы по заголовку и описанию, а администраторы могут фильтровать записи, исходя из их местонахождения.
Вывод местонахождений с помощью инструмента администратора



Система передачи адресов URL в Django использует модули конфигураций регулярных выражений, которые отображают строковые шаблоны URL в методах языка Python, называемые видами. Эта система позволяет совершенно четко отделять адреса URL от кода, что делает их максимально легкими для управления.

Модуль urls.py создается и определяется в качестве начала отсчета конфигурации URL (с помощью значения ROOT_URLCONF в модуле settings.py). Единственное требование для файла конфигурации URL состоит в том, что он должен содержать объект, определяющий шаблоны, называемые urlpatterns.

Приложение управления работой (job) будет начинаться с index-видом и детальным (detail) видом, которые доступны через настоящие отображения URL:

  • /jobs index-вид: Отображает последние 10 работ
  • /jobs/1 детальный вид: Отображает работы с одним идентификационным номером (ID)

Оба этих вида (index и детальный вид) будут выполнены в модуле, называемом views.py в приложении работ. Выполнение этой конфигурации в файле urls.py проекта будут выглядеть следующим образом:
Листинг 21. Выполнение конфигурации видов в djproject/urls.py

from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^admin/', include('django.contrib.admin.urls.admin')), (r'^jobs/$', 'djproject.jobs.views.index'), (r'^jobs/(?Pd+)/$', 'djproject.jobs.views.detail'), )

Отметьте кусочек кода . Это понадобиться позже.

На практике лучше всего - вытаскивать шаблоны URL, специальные для приложений, и помещать их в само приложение. Это отделяет приложение от проекта и позволяет повторно его использовать. Файл конфигурации URL уровня приложений для работ (jobs) будут выглядеть так:
Листинг 22. Файл конфигурации URL уровня приложений, urls.py

from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^$', 'djproject.jobs.views.index'), (r'^(?Pd+)/$', 'djproject.jobs.views.detail'), )

С тех пор, как методы видов исходят из одного модуля, для настройки djproject.jobs.views в качестве корневого имени модуля можно использовать первый аргумент, и Django использует его для того, чтобы искать методы index и detail:
Листинг 23. jobs/urls.py: поиск index и detail

from django.conf.urls.defaults import * urlpatterns = patterns('djproject.jobs.views', (r'^$', 'index'), (r'^(?Pd+)/$', 'detail'), )

Чтобы связать в одно целое адреса (URL), перечисленных выше работ (job), назад в проект, необходимо использовать функцию include. Адреса (URL) уровня приложений теперь связаны в разделе /jobs:
< a name="listing24">Листинг 24. djproject/urls.py: Связывание адресов (URL) обратно в проект

from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^admin/', include('django.contrib.admin.urls.admin')), (r'^jobs/', include('djproject.jobs.urls')), )

Если вы попытаетесь войти на начальную (index) страницу (http://localhost:8000/jobs) на этом этапе, используя тест-сервер, вы получите ошибку, так как вид, который будет называться (djproject.jobs.views.index), еще не существует.

Выполнение видов

Вид представляет собой простой метод языка Python, который принимает объект отклика и отвечает за:

  • Любую бизнес-логику (явно или неявно)
  • Контекстный словарь с данными для шаблона
  • Рендеринг (rendering) шаблона с контекстом
  • Объект отклика, который пропускает отрендеренные (rendered) результаты обратно в среду разработки

В Django вызванный метод языка Python, когда запрашивается URL, называется видом, а страница, закаченная и отрендеренная, видом называется шаблоном. По этой причине, команда разработчиков Django говорила о Django, как о среде разработки с MVT (model-view-template - модель-вид-шаблон). С другой стороны, TurboGears называет свои методы контроллерами, а отрендеренные шаблоны видами, что действительно позволяет использовать аббревиатуру MVC. Разница лишь в использовании слов, но смысл остается тем же.

Самый простейший из возможных видов возвращает объект HttpResponse (http отклик), инициализированный в строковый тип. создайте следующий метод и сделайте из /jobs HTTP-запрос, чтобы проверить, что ваши файлы urls.py и views.py правильно настроены.
Листинг 25. jobs/views.py (v1)

from django.http import HttpResponse def index(request): return HttpResponse("Job Index View")

Следующий код получает последние 10 работ (job), рендерит их через шаблон и возвращает отклик. Это не будет работать без файла шаблона из следующего раздела.
Листинг 26. jobs/views.py (v2)

from django.template import Context, loader from django.http import HttpResponse from jobs.models import Job def index(request): object_list = Job.objects.order_by('-pub_date')[:10] t = loader.get_template('jobs/job_list.html') c = Context({ 'object_list': object_list, }) return HttpResponse(t.render(c))

В вышеприведенном коде шаблон назван, как строковый jobs/job_list.html. Рендеринг шаблона происходит в контексте списка работ (job), названном object_list. Отрендеренный шаблон строки попадает в конструктор HTTPResponse, который отправляется назад в клиент запроса с помощью среды разработки.

Этапы загрузки шаблона, создающие контекст и возвращающие новый объект отклика, перемещены ниже с помощью удобного метода, называемого render_to_response. Также новым является метод детального (detail) вида, который использует удобный для этого метод get_object_or_404, чтобы осуществить выборку объекта Job, используя приведенные аргументы. Если объект не найден, то выдается ошибка 404. Эти два метода избавляют программу от большого количества стандартных кодов, используемых в большинстве Web-приложений.
Листинг 27. jobs/views.py (v3)

from django.shortcuts import get_object_or_404, render_to_response from jobs.models import Job def index(request): object_list = Job.objects.order_by('-pub_date')[:10] return render_to_response('jobs/job_list.html', {'object_list': object_list}) def detail(request, object_id): job = get_object_or_404(Job, pk=object_id) return render_to_response('jobs/job_detail.html', {'object': job})

Отметим, что detail берет object_id в качестве аргумента. Этот номер упоминался раньше, после URL-пути /jobs/ к файлу работ (job) urls.py. Он проходит дальше в метод get_object_or_404 в качестве первичного ключа (primary key - pk).

Приведенные выше виды все еще не будут работать, потому что шаблоны, которые они загружают и рендерят (jobs/job_list.html и jobs/job_detail.html) еще не существуют.

Создание шаблонов

Django предоставляет простой язык шаблонов, спроектированный для быстрого рендеринга и простоты использования. Шаблоны Django создаются из простого текста, встроенного в {{ переменные }} и {% тэги %}. Затем происходит замена переменных на значения, которые они несут. Тэги используются в качестве основы логики управления. Шаблоны можно использовать для генерирования любого формата текстов, включая HTML, XML, CSV и простой текст.

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

TEMPLATE_DIRS = ( '/path/to/devdir/djproject/templates/', )

Шаблоны в Django поддерживают концепцию, называемую наследованием шаблонов, которая позволяет дизайнерам сайтов создавать однородный вид и функциональность без повторения содержания в каждом из шаблонов. Вы можете использовать наследование, определяя документ скелета, или основы, с блочными тэгами. Эти блочные тэги заполняются шаблонами страниц с содержанием. Этот пример показывает скелет кода на HTML с блоками, называемыми title, extrahead и content:
Листинг 29. Документ скелета, templates/base.html

{% block extrahead %}{% endblock %} {% block content %}{% endblock %}

Чтобы приложение было отдельно от проекта, используйте вспомагательный файл основы, в качестве основы для всех файлов страниц приложения Job. Для этого примера, поместите CSS приложения в файл основы для упрощения. В реальном приложении, с хорошо сконфигурированным Web-сервером, возьмите данный CSS и поместите его в статичный файл, обслуживаемый Web-сервером.
Листинг 30. Вспомогательный файл основы, templates/jobs/base.html

{% extends "base.html" %} {% block extrahead %} {% endblock %}

Изначально, тест-сервер в Django не обслуживает статичные файлы, потому что эту работу должен выполнять Web-сервер. Если во время разработки вы захотите, чтобы Django работал с картинками, листами стилей и так далее, тогда см. ссылку в Ресурсах о том, как включить эту возможность.

Теперь создайте 2 шаблона страниц для загрузки и рендеринга. Шаблон jobs/job_list.html просто выполняет итерацию через object_list (список объектов), который он получает через контекст, выдаваемый index-видом, а также отображает ссылку на каждую из страниц с подробной информацией о записи.
Листинг 31. Шаблон templates/jobs/job_list.html

{% extends "jobs/base.html" %} {% block title %}Job List{% endblock %} {% block content %} Job List {% endblock %}

Страница jobs/job_detail.html показывает одну запись, называемую job (работа):
Листинг 32. Страница templates/jobs/job_detail.html

{% extends "jobs/base.html" %} {% block title %}Job Detail{% endblock %} {% block content %} Job Detail
{{ job.job_title }} - {{ job.location }}
Posted: {{ job.pub_date|date:"d-M-Y" }}
{{ job.job_description }}
{% endblock %}

Язык шаблонов в Django был спроектирован с ограниченными функциональными возможностями. Эта ограниченность позволяет сохранять простоту шаблонов для непрограммистов и ограждает программистов от использования бизнес-логики там, где ее не должно быть, в слое представления. См. ссылку на документацию по языку шаблонов в Ресурсах.

Универсальные виды

Django идет вместе с четырьмя наборами универсальных видов, которые позволяют разработчикам создавать приложения, следующие типичным шаблонам:

  • Страницы со списком/подробностями (как вышеприведенный пример)
  • Дробление записей по дате (полезно для новостных сайтов и блогов)
  • Создание, обновление и удаление - СОУ (Creation, update, and deletion - CRUD) объектов
  • Простой прямой рендеринг шаблонов или простое HTTP-перенаправление

Вместо создания методов стандартных видов, вся бизнес-логика находится в файле urls.py и управляется с помощью методов универсальных видов, поддерживаемых Django.
Листинг 33. Универсальные виды в jobs/urls.py

from django.conf.urls.defaults import * from jobs.models import Job info_dict = { 'queryset': Job.objects.all(), } urlpatterns = patterns('django.views.generic.list_detail', (r'^$', 'object_list', info_dict), (r'^(?Pd+)/$', 'object_detail', info_dict), )

Три важных изменения в данном файле urls.py:

  • Объект отображения info_dict проходит через набор запросов, чтобы был открыт доступ для Jobs.
  • Он использует django.views.generic.list_detail вместо djproject.jobs.views.
  • Действительно вызванные виды - это object_list и object_detail.

Этот проект следует некоторым требованиям, чтобы переход к универсальным видам произошел автоматически:

  • Универсальный детальный (detail) вид ожидает аргумент с именем object_id.
  • Шаблоны следуют наименованию: app_label/model_name_list.html (jobs/job_list.html) app_label/model_name_detail.html (jobs/job_detail.html)
  • Шаблон списка управляет списком с именем object_list.
  • Детальный шаблон управляет объектом с именем object.

Больше опций можно задать через info_dict, включая значение paginate_by, которое определяет число объектов на странице.

Заключение

Следующая статья этого выпуска будет рассматривать TurboGears, другую среду Web-разработки на языке Python, и будет сравнивать его с Django.

Ресурсы

Научиться

Получить продукты и технологии

  • Закажите SEK для Linux, коробка с двумя DVD, содержащими последние пробные версии ПО IBM для Linux: DB2®, Lotus®, Rational®, Tivoli® и WebSphere®.
  • Доступное пробное ПО IBM для скачивания прямо с сайта developerWorks, чтобы вы могли создавать следующие разработки под Linux.

Обсудить

Об авторе

Йен Маурер (Ian Maurer) - главный консультант в Brulant, Inc., где он специализируется на интегрированных решениях в электронной коммерции (e-commerce), использующих открытое ПО и технологии IBM WebSphere в различных отраслях, включая товары широкого потребления и розничную торговлю. Йен проживает в северо-восточной части штата Огайо (Ohio) и является членом Cleveland Area Python Interest Group.

К содержанию

{% block extrahead %}{% endblock %} {% block content %}{% endblock %}

Чтобы приложение было отдельно от проекта, используйте вспомагательный файл основы, в качестве основы для всех файлов страниц приложения Job. Для этого примера, поместите CSS приложения в файл основы для упрощения. В реальном приложении, с хорошо сконфигурированным Web-сервером, возьмите данный CSS и поместите его в статичный файл, обслуживаемый Web-сервером.
Листинг 30. Вспомогательный файл основы, templates/jobs/base.html

{% extends "base.html" %} {% block extrahead %} {% endblock %}

Изначально, тест-сервер в Django не обслуживает статичные файлы, потому что эту работу должен выполнять Web-сервер. Если во время разработки вы захотите, чтобы Django работал с картинками, листами стилей и так далее, тогда см. ссылку в Ресурсах о том, как включить эту возможность.

Теперь создайте 2 шаблона страниц для загрузки и рендеринга. Шаблон jobs/job_list.html просто выполняет итерацию через object_list (список объектов), который он получает через контекст, выдаваемый index-видом, а также отображает ссылку на каждую из страниц с подробной информацией о записи.
Листинг 31. Шаблон templates/jobs/job_list.html

{% extends "jobs/base.html" %} {% block title %}Job List{% endblock %} {% block content %} Job List {% endblock %}

Страница jobs/job_detail.html показывает одну запись, называемую job (работа):
Листинг 32. Страница templates/jobs/job_detail.html

{% extends "jobs/base.html" %} {% block title %}Job Detail{% endblock %} {% block content %} Job Detail
{{ job.job_title }} - {{ job.location }}
Posted: {{ job.pub_date|date:"d-M-Y" }}
{{ job.job_description }}
{% endblock %}

Язык шаблонов в Django был спроектирован с ограниченными функциональными возможностями. Эта ограниченность позволяет сохранять простоту шаблонов для непрограммистов и ограждает программистов от использования бизнес-логики там, где ее не должно быть, в слое представления. См. ссылку на документацию по языку шаблонов в Ресурсах.

Универсальные виды

Django идет вместе с четырьмя наборами универсальных видов, которые позволяют разработчикам создавать приложения, следующие типичным шаблонам:

  • Страницы со списком/подробностями (как вышеприведенный пример)
  • Дробление записей по дате (полезно для новостных сайтов и блогов)
  • Создание, обновление и удаление - СОУ (Creation, update, and deletion - CRUD) объектов
  • Простой прямой рендеринг шаблонов или простое HTTP-перенаправление

Вместо создания методов стандартных видов, вся бизнес-логика находится в файле urls.py и управляется с помощью методов универсальных видов, поддерживаемых Django.
Листинг 33. Универсальные виды в jobs/urls.py

from django.conf.urls.defaults import * from jobs.models import Job info_dict = { 'queryset': Job.objects.all(), } urlpatterns = patterns('django.views.generic.list_detail', (r'^$', 'object_list', info_dict), (r'^(?Pd+)/$', 'object_detail', info_dict), )

Три важных изменения в данном файле urls.py:

  • Объект отображения info_dict проходит через набор запросов, чтобы был открыт доступ для Jobs.
  • Он использует django.views.generic.list_detail вместо djproject.jobs.views.
  • Действительно вызванные виды - это object_list и object_detail.

Этот проект следует некоторым требованиям, чтобы переход к универсальным видам произошел автоматически:

  • Универсальный детальный (detail) вид ожидает аргумент с именем object_id.
  • Шаблоны следуют наименованию: app_label/model_name_list.html (jobs/job_list.html) app_label/model_name_detail.html (jobs/job_detail.html)
  • Шаблон списка управляет списком с именем object_list.
  • Детальный шаблон управляет объектом с именем object.

Больше опций можно задать через info_dict, включая значение paginate_by, которое определяет число объектов на странице.

Заключение

Следующая статья этого выпуска будет рассматривать TurboGears, другую среду Web-разработки на языке Python, и будет сравнивать его с Django.

Ресурсы

Научиться

Получить продукты и технологии

  • Закажите SEK для Linux, коробка с двумя DVD, содержащими последние пробные версии ПО IBM для Linux: DB2®, Lotus®, Rational®, Tivoli® и WebSphere®.
  • Доступное пробное ПО IBM для скачивания прямо с сайта developerWorks, чтобы вы могли создавать следующие разработки под Linux.

Обсудить

Об авторе

Йен Маурер (Ian Maurer) - главный консультант в Brulant, Inc., где он специализируется на интегрированных решениях в электронной коммерции (e-commerce), использующих открытое ПО и технологии IBM WebSphere в различных отраслях, включая товары широкого потребления и розничную торговлю. Йен проживает в северо-восточной части штата Огайо (Ohio) и является членом Cleveland Area Python Interest Group.

К содержанию

15 мая 2007 Г.

Web- Python, 1

Web- Python, 1

Web Django Python

Web- Django Python, Web-

:
: IBM developerWorks

, Senior Consultant, Brulant, Inc.

, Django - Web- -- (model-view-controller - MVC), Python. Django , Web-, .

Django . Web- - 2005 . Django :

  • - (object-relational mapping)
  • ,
  • (URL)
  • ,

- Web- Python. TurboGears.

, Python , . , Python, , python -V. Django 2.3.5, Web- Python (. ). MVC.

Django

Django , , Django. 0.95. Django Web- ( . ).

Django :


1. Django

~/downloads# svn co http://code.djangoproject.com/svn/django/trunk/ django_src
~/downloads# cd django_src
~/downloads# python setup.py install

Django

Django Django, django-admin.py, path. 2 , :


2. Django

~/dev$ django-admin.py
usage: django-admin.py action [options]
actions:
  adminindex [modelmodule ...]
    Prints the admin-index template snippet for the given model
    module name(s).

  ... snip ...

  startapp [appname]
    Creates a Django app directory structure for the given app name
    in the current directory.

  startproject [projectname]
    Creates a Django project directory structure for the given
    project name in the current directory.

  validate
    Validates all installed models.

options:
  -h, --help		show this help message and exit
  --settings=SETTINGS	Python path to settings module, e.g.
			"myproject.settings.main". If this isn't
			provided, the DJANGO_SETTINGS_MODULE
			environment variable will be used.
  --pythonpath=PYTHONPATH
			Lets you manually add a directory the Python
			path, e.g. "/home/djangoprojects/myproject".

Django

Django, django-admin startproject :


3.
	
~/dev$ django-admin.py startproject djproject

djproject, , Django:


4. djproject

__init__.py
manage.py
settings.py
urls.py

, "jobs." manage.py, django-admin.py, settings.py:


5. manage.py startapp

~/dev$ cd djproject
~/dev/djproject$ python manage.py startapp jobs

Python (view). jobs :


6. jobs

__init__.py
models.py
views.py

, Django, . , , URL. , .

Django , INSTALLED_APPS settings.py. djproject.jobs:


7. settings.py

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'djproject.jobs',
)

Django object-relational mapper (ORM), Python. Python , SQL .

ORM PostgreSQL, MySQL, SQLite, Microsoft® SQL.

SQLite, . SQLite , . SQLite, pysqlite (setuptools) (. (setuptools) , , easy_install, , ):

easy_install pysqlite

, , . SQLite .


8. settings.py

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = '/path/to/dev/djproject/database.db'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''

: (Locations) (Jobs). , ( ), . , , .


9. jobs/models.py

from django.db import models

class Location(models.Model):
    city = models.CharField(maxlength=50)
    state = models.CharField(maxlength=50, null=True, blank=True)
    country = models.CharField(maxlength=50)

    def __str__(self):
        if self.state:
            return "%s, %s, %s" % (self.city, self.state, self.country)
        else:
            return "%s, %s" % (self.city, self.country)

class Job(models.Model):
    pub_date = models.DateField()
    job_title = models.CharField(maxlength=50)
    job_description = models.TextField()
    location = models.ForeignKey(Location)

    def __str__(self):
        return "%s (%s)" % (self.job_title, self.location)

__str__ - Python, . Django , .

, manage.py sql. .


10. manage.py sql

~/dev/djproject$ python manage.py sql jobs

BEGIN;
CREATE TABLE "jobs_job" (
    "id" integer NOT NULL PRIMARY KEY,
    "pub_date" date NOT NULL,
    "job_title" varchar(50) NOT NULL,
    "job_description" text NOT NULL,
    "location_id" integer NOT NULL
);
CREATE TABLE "jobs_location" (
    "id" integer NOT NULL PRIMARY KEY,
    "city" varchar(50) NOT NULL,
    "state" varchar(50) NULL,
    "country" varchar(50) NOT NULL
);
COMMIT;

, syncdb:

~/dev/djproject$ python manage.py syncdb

, syncdb . , django.contrib.auth, , INSTALLED_APPS. , . , Django, .

Django (Manager) , objects. , , all, objects:


11. (jobs)

>>> from jobs.models import Job
>>> for job in Job.objects.all():
...     print job
      

, filter () exclude (). , , , . ("gte" "greater than or equal,"( ) "lt" "less than")( ).


12. (jobs)

>>> from jobs.models import Job
>>> from datetime import datetime

>>> q1 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1))
>>> q2 = Job.objects.exclude(pub_date__lt=datetime(2006, 1, 1))

filter exclude QuerySet, . q4, , , 1- 2006 , . (Cleveland), :


13. (jobs)

>>> from jobs.models import Job
>>> from datetime import datetime
>>> q3 = Job.objects.filter(pub_date__gte=datetime(2006, 1, 1))
>>> q4 = q3.filter(location__city__exact="Cleveland",
...                location__state__exact="Ohio")

QuerySets , , , .

(slicing) Python. , , , (OFFSET), 5, (LIMIT), 10, SQL, .


14. Python-

>>> from jobs.models import Job
>>> for job in Job.objects.all()[5:15]
...     print job

: count, , QuerySet. len Python , , , count (COUNT) SQL, . .


15.
>>> from jobs.models import Job
>>> print "Count = ", Job.objects.count()       # GOOD!
>>> print "Count = ", len(Job.objects.all())    # BAD!

, . « API » Django.



Django - . , .

, Django. , , , jobs. (django.contrib.admin) INSTALLED_APPS:


16. settings.py

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'djproject.jobs',
    'django.contrib.admin',
)

(URL) /admin, , urls.py . URL .


17. urls.py,

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls.admin')),
)

, . syncdb, :

python manage.py syncdb

, -, Django.


18. -,

~/dev/djproject$ python manage.py runserver
Validating models...
0 errors found.

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

http://localhost:8000/admin , , . , .

, Admin (). , . 19 , Location () .


19. Location

class Location(meta.Model):
    ...
    class Admin:
        list_display = ("city", "state", "country")

, (Location) .




(Records) , , list_display.




. 20 , Job:


20.

class Job(meta.Model):
    ...
    class Admin:
	list_display = ("job_title", "location", "pub_date")
	ordering = ["-pub_date"]
	search_fields = ("job_title", "job_description")
	list_filter = ("location",)

, (job) : (job), . , ( - ). , , .




URL Django , URL Python, . URL , .

urls.py URL ( ROOT_URLCONF settings.py). URL , , , urlpatterns.

(job) index- (detail) , URL:

  • /jobs index-: 10
  • /jobs/1 : (ID)

(index ) , views.py . urls.py :


21. djproject/urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls.admin')),

    (r'^jobs/$', 'djproject.jobs.views.index'),
    (r'^jobs/(?P<job_id>\d+)/$', 'djproject.jobs.views.detail'),
)

<job_id>. .

- URL, , . . URL (jobs) :


22. URL , urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^$', 'djproject.jobs.views.index'),
    (r'^(?P<job_id>\d+)/$', 'djproject.jobs.views.detail'),
)

, , djproject.jobs.views , Django , index detail:


23. jobs/urls.py: index detail

from django.conf.urls.defaults import *

urlpatterns = patterns('djproject.jobs.views',
    (r'^$', 'index'),
    (r'^(?P<object_id>\d+)/$', 'detail'),
)
      

(URL), (job), , include. (URL) /jobs:


< a name="listing24"> 24. djproject/urls.py: (URL)

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^admin/', include('django.contrib.admin.urls.admin')),
    (r'^jobs/', include('djproject.jobs.urls')),
)

(index) (http://localhost:8000/jobs) , -, , , (djproject.jobs.views.index), .



Python, :

  • - ( )
  • (rendering)
  • , (rendered)

Django Python, URL, , , , . , Django Django, MVT (model-view-template - --). , TurboGears , , MVC. , .

HttpResponse (http ), . /jobs HTTP-, , urls.py views.py .


25. jobs/views.py (v1)

from django.http import HttpResponse

def index(request):
    return HttpResponse("Job Index View")

10 (job), . .


26. jobs/views.py (v2)

from django.template import Context, loader
from django.http import HttpResponse
from jobs.models import Job

def index(request):
    object_list = Job.objects.order_by('-pub_date')[:10]
    t = loader.get_template('jobs/job_list.html')
    c = Context({
        'object_list': object_list,
    })
    return HttpResponse(t.render(c))

, jobs/job_list.html. (job), object_list. HTTPResponse, .

, , , render_to_response. (detail) , get_object_or_404, Job, . , 404. , Web-.


27. jobs/views.py (v3)

from django.shortcuts import get_object_or_404, render_to_response
from jobs.models import Job

def index(request):
    object_list = Job.objects.order_by('-pub_date')[:10]
    return render_to_response('jobs/job_list.html',
                              {'object_list': object_list})

def detail(request, object_id):
    job = get_object_or_404(Job, pk=object_id)
    return render_to_response('jobs/job_detail.html',
                              {'object': job})

, detail object_id . , URL- /jobs/ (job) urls.py. get_object_or_404 (primary key - pk).

, , (jobs/job_list.html jobs/job_detail.html) .



Django , . Django , {{ }} {% %}. , . . , HTML, XML, CSV .

, - . , djproject TEMPLATE_DIRS settings.py:


28. settings.py

TEMPLATE_DIRS = (
    '/path/to/devdir/djproject/templates/',
)

Django , , . , , , . . HTML , title, extrahead content:


29. , templates/base.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <title>Company Site: {% block title %}Page{% endblock %}</title>
    {% block extrahead %}{% endblock %}
  </head>

  <body>
    {% block content %}{% endblock %}
  </body>
</html>

, , Job. , CSS . , Web-, CSS , Web-.


30. , templates/jobs/base.html

{% extends "base.html" %}

{% block extrahead %}
    <style>
        body {
            font-style: arial;
        }
        h1 {
            text-align: center;
        }
        .job .title {
            font-size: 120%;
            font-weight: bold;
        }
        .job .posted {
            font-style: italic;
        }
    </style>
{% endblock %}

, - Django , Web-. , Django , , . , .

2 . jobs/job_list.html object_list ( ), , index-, .


31. templates/jobs/job_list.html

{% extends "jobs/base.html" %}

{% block title %}Job List{% endblock %}

{% block content %}
    <h1>Job List</h1>

    <ul>
    {% for job in object_list %}
        <li><a href="{{ job.id }}">{{ job.job_title }}</a></li>
    {% endfor %}
    </ul>
{% endblock %}

jobs/job_detail.html , job ():


32. templates/jobs/job_detail.html

{% extends "jobs/base.html" %}

{% block title %}Job Detail{% endblock %}

{% block content %}
    <h1>Job Detail</h1>

    <div class="job">
        <div class="title">
            {{ job.job_title }}
            -
            {{ job.location }}
        </div>
        <div class="posted">
            Posted: {{ job.pub_date|date:"d-M-Y" }}
        </div>

        <div class="description">
            {{ job.job_description }}
        </div>
    </div>
{% endblock %}

Django . - , , . . .



Django , , :

  • / ( )
  • ( )
  • , - (Creation, update, and deletion - CRUD)
  • HTTP-

, - urls.py , Django.


33. jobs/urls.py

from django.conf.urls.defaults import *
from jobs.models import Job

info_dict = {
    'queryset': Job.objects.all(),
}

urlpatterns = patterns('django.views.generic.list_detail',
    (r'^$', 'object_list', info_dict),
    (r'^(?P<object_id>\d+)/$', 'object_detail', info_dict),
)

urls.py:

  • info_dict , Jobs.
  • django.views.generic.list_detail djproject.jobs.views.
  • - object_list object_detail.

, :

  • (detail) object_id.
  • : app_label/model_name_list.html (jobs/job_list.html) app_label/model_name_detail.html (jobs/job_detail.html)
  • object_list.
  • object.

info_dict, paginate_by, .



TurboGears, Web- Python, Django.


  • SEK Linux, DVD, IBM Linux: DB2®, Lotus®, Rational®, Tivoli® WebSphere®.
  • IBM developerWorks, Linux.

(Ian Maurer) - Brulant, Inc., (e-commerce), IBM WebSphere , . - (Ohio) Cleveland Area Python Interest Group.