Главная | Архив новостей | Общение | Площадка | Примеры OpenID
Хостинг Django от «Джино»
Оглавление

Глава 8. Усовершенствованные представления и схемы URL

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

Перевод © Попов Руслан <radz • yandex • ru>

В главе «Представления и привязки URL» мы рассказали об основах функций представлений Django и о схеме URL, в которой определено соответствие URL этим функциям. Эта глава остановится на этих вопросах более подробно.

Схема URL: полезные приёмы

В схеме URL нет ничего особенного, как всё остальное в Django, это просто код на языке Python. Вы можете использовать это знание различными способами, как показано в разделах главы далее.

Упорядочивание функций импорта

Рассмотрим нижеприведённый файл со схемой URL::

from django.conf.urls.defaults import *
from mysite.views import current_datetime, hours_ahead, hours_behind, 
                         now_in_chicago, now_in_london

urlpatterns = patterns('',
    (r'^now/$', current_datetime),
    (r'^now/plus(\d{1,2})hours/$', hours_ahead),
    (r'^now/minus(\d{1,2})hours/$', hours_behind),
    (r'^now/in_chicago/$', now_in_chicago),
    (r'^now/in_london/$', now_in_london),
)

Как объяснялось в главе «Представления и привязки URL», каждый шаблон схемы URL ассоциирован с функцией представления, которая указывается в виде функционального объекта. Это означает, что необходимо импортировать функции представления вначале модуля.

Но по мере усложнения Django приложения, его схема URL также растёт, управление этими импортами может быть утомительным. (Для каждой новой функции представления вам потребуется не забыть об её импорте, это скажется на размере оператора импорта.) Есть возможность избежать этого, просто импортируя сам модуль views. Нижеприведённый пример эквивалентен предыдущему:

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^now/$', views.current_datetime),
    (r'^now/plus(\d{1,2})hours/$', views.hours_ahead),
    (r'^now/minus(\d{1,2})hours/$', views.hours_behind),
    (r'^now/in_chicago/$', views.now_in_chicago),
    (r'^now/in_london/$', views.now_in_london),
)

Django предоставляет другой способ указания функции представления для определённого шаблона в схеме URL. Вы можете передать строку, которая содержит имя модуля и имя функции, вместо передачи самого объекта. Продолжаем работу над нашим примером:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^now/$', 'mysite.views.current_datetime'),
    (r'^now/plus(\d{1,2})hours/$', 'mysite.views.hours_ahead'),
    (r'^now/minus(\d{1,2})hours/$', 'mysite.views.hours_behind'),
    (r'^now/in_chicago/$', 'mysite.views.now_in_chicago'),
    (r'^now/in_london/$', 'mysite.views.now_in_london'),
)

Следует отметить кавычки вокруг имён представления!

Используя этот метод, больше нет необходимости импортировать функции представления. Django автоматически импортирует соответствующую функцию представления как только она понадобится, в соответствии с текстовым описанием её имени и пути.

Ещё сильнее код можно сократить, используя общий префикс для пути к функциям представления. В нашем примере, каждая строка начиналась с «mysite.views», т.е. опять дублирование. Мы можем исключить этот общий префикс и передать его в качестве первого аргумента функции patterns(), например так:

from django.conf.urls.defaults import *

urlpatterns = patterns('mysite.views',
    (r'^now/$', 'current_datetime'),
    (r'^now/plus(\d{1,2})hours/$', 'hours_ahead'),
    (r'^now/minus(\d{1,2})hours/$', 'hours_behind'),
    (r'^now/in_chicago/$', 'now_in_chicago'),
    (r'^now/in_london/$', 'now_in_london'),
)

Следует заметить, что не надо ставить завершающую точку в префикс и не надо ставить точку перед именами функций представления. Всё это будет автоматически сделано Django.

Так какой из этих двух подходов лучше? Это зависит от вашего стиля написания кода и ваших нужд.

Преимущества использования строк вместо объектов:

  • Краткий код, т.к. не требуется импортировать функции представления.

  • Более читаемая и управляемая схема URL в случае, если ваши функции представления располагаются в нескольких различных модулях.

Преимущества использования объектов вместо строк:

  • Простая замена функций представления. Обратитесь к разделу «Wrapping View Functions» FIXME (что-то нет такого в оригинальной книге) в этой главе.

  • Стиль Python, сохраняются его традиции, такие как передача функции в виде объекта.

Оба подхода правильные. Вы можете смешивать их в одном файле, описывающем схему URL. Это ваш выбор.

Использование множества префиксов для представлений

На практике при использовании строчной методики вы можете столкнуться с ситуацией, когда функции представления в схеме URL не будут иметь общего префикса. Однако, это не помешает вам воспользоваться преимуществами префикса. Просто добавьте нужное количество patterns(), вот так:

# Раньше
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^/?$', 'mysite.views.archive_index'),
    (r'^(\d{4})/([a-z]{3})/$', 'mysite.views.archive_month'),
    (r'^tag/(\w+)/$', 'weblog.views.tag'),
)

# Теперь
from django.conf.urls.defaults import *

urlpatterns = patterns('mysite.views',
    (r'^/?$', 'archive_index'),
    (r'^(\d{4})/([a-z]{3})/$', 'archive_month'),
)

urlpatterns += patterns('weblog.views',
    (r'^tag/(\w+)/$', 'tag'),
)

Всё, о чём заботится среда разработки, — это о существовании переменной urlpatterns. Эта переменная может быть создана динамически, как это показано в примере.

Специальные URL в режиме отладки

Говоря о динамическом построении urlpatterns, вы можете пожелать использовать преимущества этой методики для изменения поведения вашей схемы URL при работе Django в режиме отладки. Чтобы осуществить это, просто проверяйте значение параметра DEBUG во время работы приложения, вот так:

from django.conf.urls.defaults import*
from django.conf import settings

urlpatterns = patterns('',
    (r'^$', 'mysite.views.homepage'),
    (r'^(\d{4})/([a-z]{3})/$', 'mysite.views.archive_month'),
)

if settings.DEBUG:
    urlpatterns += patterns('',
        (r'^debuginfo$', 'mysite.views.debug'),
    )

В этом примере URL /debuginfo/ будет работать, только если параметр DEBUG установлен в True.

Использование именованных групп

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

Именованные аргументы и обязательные аргументы

Функция в языке Python может быть вызвана с использованием именованных аргументов или с помощью обязательных аргументов, а в некоторых случаях, эти аргументы можно смешивать. При использовании именованных аргументов вы должны указать имена и значения аргументов. В противном случае вы просто передаёте значения, они будут назначены аргументам по порядку их определения в функции.

Например, рассмотрим эту простую функцию:

def sell(item, price, quantity):
    print "Selling %s unit(s) of %s at %s" % (quantity, item, price)

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

sell('Socks', '$2.50', 6)

Для вызова функции с помощью именованных аргументов следует указать имена и значения аргументов. Следующие операторы эквивалентны предыдущему примеру:

sell(item='Socks', price='$2.50', quantity=6)
sell(item='Socks', quantity=6, price='$2.50')
sell(price='$2.50', item='Socks', quantity=6)
sell(price='$2.50', quantity=6, item='Socks')
sell(quantity=6, item='Socks', price='$2.50')
sell(quantity=6, price='$2.50', item='Socks')

Наконец, мы можете смешивать эти два подхода, пока обязательные аргументы находятся на своих местах. Следующие операторы эквивалентны предыдущим примерам:

sell('Socks', '$2.50', quantity=6)
sell('Socks', price='$2.50', quantity=6)
sell('Socks', quantity=6, price='$2.50')

В регулярных выражениях Python синтаксис для именованных групп регулярных выражений будет таким: (?P<name>pattern), где name является именем группы, а pattern — неким шаблоном.

Ниже дан пример файла со схемой URL, в котором используются неименованные группы:

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^articles/(\d{4})/$', views.year_archive),
    (r'^articles/(\d{4})/(\d{2})/$', views.month_archive),
)

Теперь приведём тот же файл, который переписан с использованием именованных групп:

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^articles/(?P<year>\d{4})/$', views.year_archive),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive),
)

Этот пример аналогичен предыдущему за исключением одного тонкого различия: полученные значения передаются в функции представления в виде именованных аргументов.

Например, при использовании неименованных групп запрос к /articles/2006/03/ будет преобразован к такому вызову функции:

month_archive(request, '2006', '03')

Однако при использовании именованных групп тот же самый запрос будет преобразован к такому вызову функции:

month_archive(request, year='2006', month='03')

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

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

Понимание алгоритма совпадения/группировки

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

  • Если есть хотя бы один именованный аргумент, то неименованные аргументы игнорируются.

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

  • В обоих случаях передаётся дополнительная информация в виде именованного аргумента. Читайте далее для получения подробностей.

Передача дополнительных аргументов в функции представления

Случается, что иногда приходится писать незначительно различающиеся функции представления. Например, скажем у вас есть два представления, чьё содержимое идентично, исключая шаблоны, которые они используют:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^foo/$', views.foo_view),
    (r'^bar/$', views.bar_view),
)

# views.py

from django.shortcuts import render_to_response
from mysite.models import MyModel

def foo_view(request):
    m_list = MyModel.objects.filter(is_new=True)
    return render_to_response('template1.html', {'m_list': m_list})

def bar_view(request):
    m_list = MyModel.objects.filter(is_new=True)
    return render_to_response('template2.html', {'m_list': m_list})

Мы сами дублируем код и это не элегантно. Сначала вы можете решить убрать избыточность просто используя одно и то же представления для обоих URL, поставите скобки в URL для того, чтобы получить его и проверить, чтобы определить какой шаблон надо использовать, например так:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^(foo)/$', views.foobar_view),
    (r'^(bar)/$', views.foobar_view),
)

# views.py

from django.shortcuts import render_to_response
from mysite.models import MyModel

def foobar_view(request, url):
    m_list = MyModel.objects.filter(is_new=True)
    if url == 'foo':
        template_name = 'template1.html'
    elif url == 'bar':
        template_name = 'template2.html'
    return render_to_response(template_name, {'m_list': m_list})

Проблема такого решения заключается в том, что URL переносятся в код. Если вы решите переименовать foo в fooey, вам потребуется не забыть внести изменения в код функции представления.

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

Учитывая это, мы можем переписать наш предыдущий пример так:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),
    (r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),
)

# views.py

from django.shortcuts import render_to_response
from mysite.models import MyModel

def foobar_view(request, template_name):
    m_list = MyModel.objects.filter(is_new=True)
    return render_to_response(template_name, {'m_list': m_list})

Как можно увидеть, шаблон в схеме URL имеет третий параметр.

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

Следующие секции содержат ряд идей о том как вы можете использовать эту методику в своих проектах.

Faking Captured URLconf Values

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

Например, у вас может быть приложение, которое отображает некие данные для определённого дня, вот с такими URL:

/mydata/jan/01/
/mydata/jan/02/
/mydata/jan/03/
# ...
/mydata/dec/30/
/mydata/dec/31/

Довольно просто это обработать, используя синтаксис именованных групп:

urlpatterns = patterns('',
    (r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),
)

А сигнатура функции представления станет такой:

def my_view(request, month, day):
    # ....

Это прямолинейный подход, ничего подобного раньше вы не видели. Эта уловка пригодится когда понадобится добавить другой URL, который будет использовать my_view, но её URL не будет обрабатывать month и/или day.

Например, вы можете добавить другой URL, /mydata/birthday/, который будет аналогичен /mydata/jan/06/. В этом случае использование дополнительного параметра даст вам преимущество:

urlpatterns = patterns('',
    (r'^mydata/birthday/$', views.my_view, {'month': 'jan', 'day': '06'}),
    (r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),
)

Секрет в том, что не требуется вносить какие-либо изменения в код функции представления. Функция должна обрабатывать параметры month и day, не важно получены ли они из URL или через дополнительные параметры.

Переход к обобщённым представлениям

Снижение количества дублирующего кода является хорошим тоном разработки программного обеспечения. Например, эти функции, написанные на языке Python:

def say_hello(person_name):
    print 'Hello, %s' % person_name

def say_goodbye(person_name):
    print 'Goodbye, %s' % person_name

мы можем упростить, выделив приветствие в параметр функции:

def greet(person_name, greeting):
    print '%s, %s' % (greeting, person_name)

Вы можете использовать эту философию применимо к представлениям Django, используя дополнительные параметры шаблонов схемы URL.

Учитывая это, вы можете начать создание высокоуровневых абстракций для ваших представлений. Вместо того, чтобы думать «Это представление отображает список объектов Event» или «Это представление отображает список объектов BlogEntry», рассматривайте их как два особых случая «Представление, которое отображает список объектов, где тип объекта является переменной».

Для примера рассмотрим следующий код:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^events/$', views.event_list),
    (r'^blog/entries/$', views.entry_list),
)

# views.py

from django.shortcuts import render_to_response
from mysite.models import Event, BlogEntry

def event_list(request):
    obj_list = Event.objects.all()
    return render_to_response('mysite/event_list.html', {'event_list': obj_list})

def entry_list(request):
    obj_list = BlogEntry.objects.all()
    return render_to_response('mysite/blogentry_list.html', {'entry_list': obj_list})

Эти два представления делают то же самое: они отображают список объектов. Таким образом, можно упростить тип объекта, который они отображают:

# urls.py

from django.conf.urls.defaults import *
from mysite import models, views

urlpatterns = patterns('',
    (r'^events/$', views.object_list, {'model': models.Event}),
    (r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}),
)

# views.py

from django.shortcuts import render_to_response

def object_list(request, model):
    obj_list = model.objects.all()
    template_name = 'mysite/%s_list.html' % model.__name__.lower()
    return render_to_response(template_name, {'object_list': obj_list})

Внеся небольшие изменения, мы неожиданно получили образцовое представление, пригодное для многократного использования. Начиная с этого момента, как только нам понадобится представление, которое отображает набор объектов в виде списка, мы можем просто использовать представление object_list, вместо создания ещё одного представления. Теперь рассмотрим, что же мы сделали:

  • Мы напрямую передаём классы модели, используя параметр model. Словарь с дополнительными параметрами может передавать в представление объект Python любого типа, а не только строки.

  • Строка model.objects.all() является примером утиного набора FIXME: «Если это ходит как утка и разговаривает как утка, мы можем считать это уткой.» Следует отметить, что код ничего не знает о типе объекта model, единственное требование — model должна иметь атрибут objects, который как раз есть у метода all().

  • Мы используем model.__name__.lower() для того, чтобы определить имя шаблона. В Python каждый класс имеет атрибут __name__, который содержит имя класса. Эта особенность полезна в подобных случаях, когда мы не знаем имя класса во время работы приложения. Например, атрибут __name__ класса BlogEntry содержит строку «BlogEntry».

  • Разница между примерами в том, что мы передаём обобщённую переменную object_list в шаблон. Мы могли легко изменить имя этой переменной на blogentry_list или event_list, но оставим это в качестве домашнего задания.

Так как сайты, хранящие свои данные в базах данных, используют одинаковые шаблоны, Django поставляется с набором «общие представления», который используется вышеописанную методику для сохранения вашего времени. Мы рассмотрим встроенные общие представления Django в следующей главе.

Giving a View Configuration Options

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

Чаще всего изменению подвергаются имена шаблонов:

def my_view(request, template_name):
    var = do_something()
    return render_to_response(template_name, {'var': var})

Understanding Precedence of Captured Values vs. Extra Options

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

Например:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^mydata/(?P<id>\d+)/$', views.my_view, {'id': 3}),
)

В данном примере параметр id находится и в регулярном выражении и в словаре дополнительных параметров. Параметр из словаря получает преимущество. Это означает, что любой запрос (т.е., /mydata/2/ или /mydata/432432/) будет интерпретирован как-будто бы параметр id установлен в 3, независимо от значения в URL.

Проницательные читатели отметят, что в данном случае захват переменной id с помощью регулярного выражения — это просто трата времени, так как полученное значение будет всегда перекрываться значением параметра id из словаря. Это правильное поведение, мы напоминаем об этом лишь для того, чтобы вы не сделали ошибку.

Использование стандартных аргументов для представления

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

Пример:

# urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^blog/$', views.page),
    (r'^blog/page(?P<num>\d+)/$', views.page),
)

# views.py

def page(request, num="1"):
    # Output the appropriate page of blog entries, according to num.
    # ...

В данном примере оба шаблона URL указывают на одно и то же представление, views.page, но первый шаблон не получает параметров из URL. Если срабатывает первый шаблон, то будет выполнена функция page() будет использовать стандартные значения аргументов (num=1). Если срабатывает второй шаблон, функция page() будет использовать значение для параметра num полученное с помощью регулярного выражения.

Как объяснялось ранее, обычно используют данную методику совместно с параметрами конфигурации. Этот пример немного улучшает пример из раздела «Giving a View Configuration Options», предоставляя стандартное значение для template_name:

def my_view(request, template_name='mysite/my_view.html'):
    var = do_something()
    return render_to_response(template_name, {'var': var})

Представления для особых случаев

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

Например, страницы «добавить объект» на сайте администратора Django представлены в схеме URL такой строкой:

urlpatterns = patterns('',
    # ...
    ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
    # ...
)

Эта строка совпадает с URL такими как /myblog/entries/add/ и /auth/groups/add/. Однако страница добавления пользователей (/auth/user/add/) является особым случаем — оно не отображает все поля формы, она отображает два поля для ввода пароля и так далее. Мы можем решить эту проблему реализовав особое поведение представления, например так:

def add_stage(request, app_label, model_name):
    if app_label == 'auth' and model_name == 'user':
        # do special-case code
    else:
        # do normal code

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

urlpatterns = patterns('',
    # ...
    ('^auth/user/add/$', 'django.contrib.admin.views.auth.user_add_stage'),
    ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
    # ...
)

Теперь вызов /auth/user/add/ будет обработан представлением user_add_stage. Несмотря на то, что этот URL совпадает со вторым шаблоном, он будет обработан первым.

Обработка совпадающего текста

Каждый аргумент, полученный из URL с помощью регулярного выражения передаётся представлению в виде обычной строки. Например:

(r'^articles/(?P<year>\d{4})/$', views.year_archive),

Аргумент year в этой строке будет передан в представление views.year_archive() в виде строки, не в виде целого числа, несмотря на то, что выражение \d{4} совпадает только со строкой чисел.

Эту особенность следует помнить при разработке приложения. Множество встроенных функций Python принимают объекты строго определённого типа. Общей ошибкой является попытка создать объект datetime.date, используя строковое представление даты, а не целочисленное:

>>> import datetime
>>> datetime.date('1993', '7', '9')
Traceback (most recent call last):
    ...
TypeError: an integer is required
>>> datetime.date(1993, 7, 9)
datetime.date(1993, 7, 9)

С точки зрения схемы URL это ошибка выглядит так:

# urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^articles/(\d{4})/(\d{2})/(\d{2})/$', views.day_archive),
)

# views.py

import datetime

def day_archive(request, year, month, day)
    # The following statement raises a TypeError!
    date = datetime.date(year, month, day)

А правильно можно написать так:

def day_archive(request, year, month, day)
    date = datetime.date(int(year), int(month), int(day))

Следует отметить, что сам метод int() вызывает исключение ValueError при передаче ему строки, в которой есть не только цифры. Но мы избегаем эту ошибку в нашем случае, так как регулярное выражения в шаблоне URL обеспечивает передачу только цифр.

Определение того, с чем совпадёт шаблон URL

При получении запроса Django пытается найти соответствующий шаблон в схеме URL как для обычной строки Python (не как для Unicode строки). При этом параметры GET и POST или доменное имя не принимаются во внимание. Также не рассматривается начальный слэш, потому что каждое URL имеет начальный слэш.

Например, в запросе http://www.example.com/myapp/ Django будет искать шаблон URL для myapp/. В запросе http://www.example.com/myapp/?page=3 Django будет искать шаблон для myapp/.

Метод запроса (т.е. GET, POST, HEAD) не принимается во внимание при обработке схемы URL. Другими словами, все методы будут обрабатываться теми же функциями. Ветвление обработки запроса в зависимости от использованного метода лежит полностью на функциях представления.


Увидели ошибку?
Выделите её мышкой и нажмите
Ctrl-Enter
Обработано:
511 49 130 71

Версия книги
1.0 2.0
Версия 2.0 в процессе перевода!

Мой луч
Многообразие света

Полезное
Актуальные вакансии, Python работа для python-разработчиков.


Скачать в формате
CHM от 2 сентября

Заказать PDF файл можно через почту, чат, джаббер. Всего 2WMZ. Содержимое точно соответствует содержимому сайта.
Чем чаще заказываете — тем больше перевожу.

Русская группа

на поддержку перевода
Яндекс Яндекс.Деньги Хочу такую же кнопку
Ускорить процесс перевода!
R130494980980
Z425285133788
E112528079659
U327380922061

Книга помогла реализовать:
Проект «Мой луч»
АРМ УФМС.


Мой вебсайт стоит666 337,31 руб

© 2008-2009 Ruslan Popov @ gmail.com Powered by Django 1.1 beta 1 SVN-11114
Главная | Архив новостей | Общение | Площадка | Примеры OpenID