Django Book: первая страница Django-проекта – "Hello, World!"

Автор: | 02/02/2015
 

django_logo_2Перевод. Оригинал тут>>>.

В статье Django: установка NGINX + uWSGI + Django на CentOS было рассказано как установить и запустить Django. В этой – мы рассмотрим создание динамических страниц с Django.

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

$ cd /var/www/django
$ django-admin startproject example
$ cd example/
$ ls -l
total 16
-rw-r--r-- 1 setevoy setevoy 0 Feb 2 14:14 __init__.py
-rwxr-xr-x 1 setevoy setevoy 503 Feb 2 14:14 manage.py
-rw-r--r-- 1 setevoy setevoy 5033 Feb 2 14:14 settings.py
-rw-r--r-- 1 setevoy setevoy 568 Feb 2 14:14 urls.py
$ django-admin --version
1.3.1

Первая страница

Для начала, давайте создадим страницу со знаменитым сообщением – “Hello world“.

Если вы раньше создавали такую страницу без использования веб-фреймворка, вы просто записывали строку “Hello world” в текстовый файл, называли его, например, hello.html, и загружали в какую-то директорию веб-сервера. Такой процесс создания веб-страницы имеет две основных состовляющих: её содержимое (строка “Hello world“), и URL (например – http://www.example.com/hello.html).

С Django надо выполнить практически то же, но немного другим образом. Содержимое страницы создаётся функцией представления (view function), а её URL указывается в URLconf-е. Для начала – давайте напишем нашу функцию представления “Hello world“.

Первое представление

Внутри директории, которая была создана при выполнении django-admin startproject создайте файл views.py. Это будет наш модуль Python, который будет хранить представления для этой статьи. Имя views.py не являетсяя каким-то особенным – для Django не имеет значения его имя, но будет хорошей идеей назвать его именно так, так как это имя модуля является общепринятым, и будет удобным для разработчиков, которым придётся сопровождать ваш код в будуем.

Содержимое нашего views.py очень простое:

from django.http import HttpResponse

def hello(request):
    return HttpResponse("Hello world")

Рассмотрим его шаг за шагом:

  • сначала мы импортируем класс HttpResponse, который находится в модуле django.http;
  • затем мы создаём функцию-представление hello. Каждая такая функция должна принимать как минимум один аргумент – request. Это объект, который содержит информацию о текущем Web-запросе, который вызывал это представление, и он является экземпляром класса django.http.HttpRequest. В этом примере мы ничего не будем с ним делать, но тем не менее он должен быть. Имя функции не имеет значения. Мы назвали её hello только потому что это имя отображает суть этого представления, но её можно было так же назвать hello_wonderful_beautiful_world. Далее, в разделе “Первый URLconf“, станет понятно как именно Django использует эту функцию;
  • наша функция содержит только одну строку, которая возвращает объект HttpResponse, который был создан с тектом “Hello world“.

Выводы из первого урока: представление является простой функцией Python, которая принимает HttpRequest в качестве первого аргумента, и возвращает экземляр HttpResponse. Для того, что бы функция Python являлась представлением Django – она должна соответствовать этим двум правилам (есть исключения, но их мы рассмотрим позже).

Первый URLconf

Если сейчас вы запустите python manage.py runserver – вы всё ещё будете видеть стартовую страницу Django, без какого-либо упоминания о нашем “Hello, World“. Это происходит потому, что наш проект example ещё ничего не знает про представление hello, которое мы создали перед этим. Нам надо указать Django явным образом, что бы вызываем это представление при обращении к конкретному URL-у. Что бы связать функцию представления с конкретным URL-ом – используется модуль URLconf.

URLconf – это что-то вроде таблицы содержания вашего Django-сайта. В основном – он связывает URL-ы и функции представлений, которые должны быть вызваны для этих URL-ов. Именно так вы сообщаете Django, что “Для этого URL-а – вызови этот код, а для этого URL-а – этот код“. Например, когда кто-то открывает адрес /foo/ – вызывать функцию представления foo_view(), которая находится в модуле Python views.py.

Когда вы выполняете команду django-admin startproject  – скрипт создаёт ваш URLconf автоматически – это файл urls.py. По умолчанию он выглядит так:

from django.conf.urls import patterns, include, url

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'mysite.views.home', name='home'),
    # url(r'^mysite/', include('mysite.foo.urls')),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # url(r'^admin/', include(admin.site.urls)),
)

Этот URLconf включает в себя несколько наиболее распространённых  возможностей Django, которые пока закомментированы. Если мы уберём все закомментированые строки – у нас останется такой код:

from django.conf.urls.defaults import patterns, include, url

urlpatterns = patterns('',
)

Примечание: для Django 1.8 URLConf должен выглядеть так:

from example.views import hello

urlpatterns = [
    url(r'^hello/$', hello),
]

Давайте построчно его рассмотрим:

  • в первой строке мы импортируем три функции из модуля django.conf.urls.defaults, которые являются системой URLconfpatterns, include и urls;
  • во второй строке вызывается функция patterns, которая сохраняет результат в переменную urlpatterns. Функция patterns принимает только один аргумент – пустую строку (хотя в строке можно передавать некоторые прекфиксы для функций представления, но их мы рассмотрим позже).

Главное, что нам надо запомнить тут – это переменная urlpatterns, которую Django ожидает увидеть в вашем модуле URLconf. Эта переменная определяет связь между URL-ами, и кодом, который будет вызываться при обращении к конкретному адресу. Как мы видим, по умолчанию URLconf пустой – ваше Django-приложение находится в “пустом” состоянии (кстати, именно так Django определяет когда показывать страницу “Welcome to Django“: если URLconf пустой – Django предполагает что вы только начали работу над проектом, и поэтому её отображает.)

Что бы добавить новый URL и предсталение к вашему URLconf – просто добавьте связь между шаблоном URL и функцией представления. Вот как это будет выглядеть для нашего представления hello:

from django.conf.urls.defaults import patterns, include, url
from example.views import hello

urlpatterns = patterns('',
 url(r'^hello/$', hello),
)

Мы сделали тут два изменения:

  1. первое – мы импортировали представление hello из модуля example/views.py, которое выглядит как example.views при использовании синтаксиса Python (т.е., предполагается, что файл views.py расположен в директории example, а путь example/views.py включён в пути поиска модулей Python, мы ещё расммотрим этот момент ниже);
  2. второе – мы добавили строку url(r'^hello/$', hello), к переменной urlpatterns. Функция url() указывает Django как обработать URL, который вы настраиваете. Первый аргумент – шаблон, регулярное выражение, описывающее URL, а второй аргумент – функция представления, которая будет вызвана для это шаблона. Функция url() может так же принмать некоторые дополнительные аргументы, их мы рассмотрим позже.

Примечание

Ещё одна важная деталь, которую мы видим в примерах выше – это символ r перед регулярным выражением. Таким образом мы сообщаем Python, что эта строка является “сырой” (raw) и обратные косые (“”) в ней не должны обрабатываться интерпретатором. В обычных Python-строках обратные косые используются для обозначения специальных символов, таких как “n” – символ новой строки. Когда вы добавляете символ rPython не будет обрабатывать “”, таким образом r'n' будет двухсимвольной строкой, содержащей символ “” и символ “n“. Так как и в Python и в регулярных выражения используется символ обратной косой черты – рекомендуется использовать “сырые строки” каждый раз, когда вы определяете регулярное выражение в Python-е.

В двух словах – мы просто говорим Django, что все запросы к URL/hello/ должны быть обработаны функцией hello.

Python Path

Python path – это список директорий в вашей системе, в которых Python будет выполнять поиск модулей при использовании import.

Например, ваш Python path установлен как ['', '/usr/lib/python2.7/site-packages', '/home/username/djcode']. Если вы выполние операцию from foo import barPython начнёт поиск модуля foo.py в текущей директории (пустой элемент в Python path обозначает текущий каталог). Если файла foo.py в нём не окажется – Python выполнит поиск в каталоге /usr/lib/python2.7/site-packages/. Если же файла не окажется и там – будет выполнен поиск в /home/username/djcode/. В конце-концов, если его не окажется и там – будет вызван ImportError.

Если вы хотите в точности узнать содержимое вашего Python path – запустите интерпретатор, и выполните следующее:

>>> import sys
>>> print sys.path

Как правило – вам не стоит беспокоиться про настройку вашего Python pathPython и Django сами позаботятся об этом (настройка Python path – одно из действий, которые выполняет скрипт manage.py).

Стоит ещё обсудить синтаксис URLpattern, так как иногда он может быть не совсем очевидным. Хотя мы хотим получить URL /hello/ – сам шаблон поиска выглядит немного по-другому. И вот почему:

  • Django удаляет символы косой черты в каждом входящем URL перед проверкой URLpatterns. Это значит, что наш URLpatterns не включает в себя ведующую косую в /hello/ (на первый взгляд это может показаться непонятным, но это поведение потом упростит некоторые другие вещи, такие как подключение одного URLconf в другом, что мы рассмотрим позже);
  • наш шаблон так же включает в себя знак вставки (^) и символ доллара ($). Это символы регулярных выражений, которые имеют особенный смысл: символ ^ означает “требуемый шаблон находится в начале строки“, а символ доллара – “требуемый шаблон находится в конце строки“. Объясним это на примере. Если мы используем шаблон в виде “^hello/“, т.е. без символа $ в конце, тогда любая строка, которая начинается с /hello/ попадёт под фильтр, например – /hello/foo, или /hello/bar, а не только /hello/. Так же, если мы уберём символ ^, и используем фильтр 'hello/$'Django обработает любой URL, который заканчивается на hello/, например – /foo/bar/hello/. Если мы укажем только hello/, без символов ^ и $ – тогда под фильтр попадёт вообще любой URL, содержащий слово hello, например – /foo/hello/bar. Если же мы используем ^ и $ – тогда под фильтр попадёт только URL /hello/ – ничего больше;
  • вам, возможно, любопытно – что будет, если в каком-то URL-е не будет закрывающей косой черты, т.е. – просто /hello, так как в нашем URLpattern она требуется в шаблоне, но её нет в запросе? Однако, по умолчанию – любой запрос к URL-у, который не совпадает с URLpattern  и не содержит / будет перенаправлен на такой же URL, но с закрывающей косой чертой (это настраивается параметром APPEND_SLASH в настройках Django). Если вы из тех людей, которые любят закрывать все URL-ы символом косой черты, то всё, что вам надо – это добавить её к каждому URLpattern и установить APPEND_SLASH в True. Если вы предпочитаете не использовать / в ваших URL-ах – установите APPEND_SLASH в False и установите URLpattern так, как считаете нужным.

Ещё одна вещь, на которую стоит обратить внимание в нашем URLconf, это то, что мы передаём функцию представления hello как объект, без вызова самой функции. Это является ключевой особенностью Python (и других динамических языков): функции являются объектами классов, а это значит, что вы можете передать их как обычные переменные.

Что бы проверить наши изменения в URLconf, запустите сервер разработки Django с помощью команды python manage.py runserver (если он всё ещё работает – его не надо перезапускать, так как он автоматически определяет изменения в коде, и перезагружает его, так что вам нет необходимости делать это вручную). Сервер запускается по адресу http://127.0.0.1:8000/ (если вы не указали другое, например – python manage.py runserver 11.222.333.11:9090), так что – откройте браузер, и перейдите на страницу http://127.0.0.1:8000/hello/ – вы должны увидеть текст “Hello world” – вывод вашего Django-представления.

Поздравляем – вы только чт осоздали вашу первую Django-страницу.

Регулярные выражения (regular expressions)

Регулярные выражения (или regex) – удобный инструмент составления шаблонов текста. Так как модуль URLconf в Django позволяет использование регулрярных выражений для поиска соответствий в URL-ах, вам потребуется знать некоторые специальные символы regex для практики. В таблице ниже предоставлены наиболее используемые из них:

Символ Значение
. (dot) любой одинарный символ
d одна любая цифра
[A-Z] любой символ от А до Z (заглавные)
[a-z] любой символ от a до z (строчные)
[A-Za-z] юбой символ от А до Z (независимый регистр)
+ одно или более предыдущего выражения (например, d+ значит одна или больше цифр)
[^/]+ Один или более символов до (но не включая) символ обратной косой
? ноль или одно предыдущих выражения (т.е.,d? – это ноль или одна цифр)
* ноль или больше предыдущих выражения (т.е, d* - это ноль, одна или больше цифр)
{1,3} между одним или тремя (включительно) предыдущих выражений, т.е., d{1,3} - это одна, две или три цифры)

Для более полной информации – смотрите http://www.djangoproject.com/r/python/re-module/ или http://rtfm.co.ua/regex-polnaya-tablica/.

Небольшая заметка про ошибки 404

В настоящий момент наш URLconf содержит только один URLpattern – он обрабатывает запросы только к URL/hello/. Что будет, если вы вызовете другой адрес?

Что бы узнать это – попробуйте запустить сервер разработки, и откройте страницу http://127.0.0.1:8000/goodbye/, или http://127.0.0.1:8000/hello/subdirectory/ или даже http://127.0.0.1:8000/  (корень сайта). Вы должны увидеть сообщение “Page not found”. Django выводит её, так как запрошенный URL не поисан в вашем URLconf. Вот как она будет выглядеть:

Django 404 page

Эта страница не только сообщает вам о 404 ошибке. Так же, она сообщает, по какому конкретно URL было обращение, и даже шаблон в  URLconf, который был использован. Благодаря этой информации – вы можете установить, почему была получена ошибка 404.

Конечно, эта информация предназначена только для вас, как для разработчика. Если это “боевой” сервер, который доступен из Интернета, вам вряд ли захочется расрыывать такую инфомарцию всем подряд.

Данная страница отображается только в том случае, если ваш Django-проект находится в debug-режиме. Мы поясним далее, как его отключить. Пока же, просто имейте ввиду, что каждый новый проект Django будет находится в дебаг-режиме. Если же его отключить – страница 404 ошибки будет другая.

Небольшая заметка про корень сайта

Как вы уже в курсе, ошибка 404 ошибка возникает даже при обращении к корню сайта – http://127.0.0.1:8000/. Django не добавляет ничего к корню проекта, а а этот URL не является чем-то особенным. Вы должны настроить URLpattern так же, как для любого другого URL в вашем URLconf.

URLpattern для корня сайта может показаться не совсем понятным, поэтому кратко коснёмся этого вопроса. Когда вы будете готовы подключить представление для корня вашего сайта – используйте URLpattern в виде '^$', который будет захватывать любые пустые строки. Например:

from mysite.views import hello, my_homepage_view

urlpatterns = patterns('',
    url(r'^$', my_homepage_view),
    # ...
)

Продолжение – Django Book: как Django обрабатывает запрос.