Можете ли вы объяснить этот простой пример из главы 3 книги Django (она касается представлений, шаблонов URL и регулярных выражений)? - PullRequest
0 голосов
/ 13 января 2012

Я пытаюсь следовать тому, что здесь объясняется: http://www.djangobook.com/en/2.0/chapter03/ (сбивающий с толку пример составляет около 4/5 пути вниз по странице).

Идея состоит в том, чтобы иметь URL, по которому можно сопоставить любой из /time/plus/1, /time/plus/2, /time/plus/3 и т. Д. - вплоть до /time/plus/99. Книга говорит:

Как же тогда мы проектируем наше приложение для обработки произвольного часа? Смещения? Ключ заключается в использовании подстановочных знаков URLpatterns. Как мы уже говорили ранее URLpattern был регулярным выражением; следовательно, мы можем использовать шаблон регулярного выражения \ d + для соответствия одной или нескольким цифрам:

Поскольку мы хотим остановиться на 99, книга предлагает использовать следующее:

urlpatterns = patterns('',
    # ...
    (r'^time/plus/\d{1,2}/$', hours_ahead),
    # ...
)

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

Теперь, когда мы определили подстановочный знак для URL, нам нужен способ передача этих подстановочных данных в функцию представления, чтобы мы могли использовать одиночная функция просмотра для любого произвольного смещения часов. Мы делаем это путем поместив скобки вокруг данных в URLpattern, которые мы хотим спасти. В нашем примере мы хотим сохранить любое число введен в URL, поэтому давайте поставим круглые скобки вокруг \d{1,2}, например это:

(r'^time/plus/(\d{1,2})/$', hours_ahead),

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

Хорошо, я понимаю, что данные собираются, но где они хранятся? Как Django узнает, что ему нужно передать захваченные данные в функцию hours_ahead? Действительно, один комментатор на сайте книг даже задает следующий вопрос:

Из описания не понятно, как сохранить введенный номер URL - поставив скобки вокруг d {1,2} - позволяет этому значению передаваться как параметр в hours_ahead.

Не могли бы вы объяснить, как полученные данные с URL-адреса передаются в функцию hours_ahead?

Если вам интересно, вот функция из файла views.py:

from django.http import Http404, HttpResponse
import datetime

def hours_ahead(request, offset):
    try:
        offset = int(offset)
    except ValueError:
        raise Http404()
    dt = datetime.datetime.now() + datetime.timedelta(hours=offset)
    html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt)
    return HttpResponse(html)

Ответы [ 2 ]

2 голосов
/ 13 января 2012

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

Передо мной нет кода Django, но вы могли бы сделать что-то подобное самостоятельно, используя модуль re и звездочку .

import re

def myfunc1arg(arg1):
    print "I got passed the argument", arg1

def myfunc2args(arg1, arg2):
    print "I got passed the arguments", arg1, "and", arg2

myfunc1arg(*re.match("args/(.*)", "args/hello").groups())

myfunc2args(*re.match("args/(.*)/(.*)", "args/hello/world").groups())

Первым аргументом для re.match является регулярное выражение (шаблон, который вы вводите в свой код), а вторым аргументом является «url». Django использует строку кода, подобную приведенной выше, чтобы вытащить группы в скобках (группы захвата) и передать их в вашу функцию.

ETA: Если вам интересно, здесь (строки 195-209) - это специальный код Django, который захватывает регулярные выражения из пути URL:

def resolve(self, path):
    match = self.regex.search(path)
    if match:
        # If there are any named groups, use those as kwargs, ignoring
        # non-named groups. Otherwise, pass all non-named arguments as
        # positional arguments.
        kwargs = match.groupdict()
        if kwargs:
            args = ()
        else:
            args = match.groups()
        # In both cases, pass any extra_kwargs as **kwargs.
        kwargs.update(self.default_args)

        return ResolverMatch(self.callback, args, kwargs, self.name)

В ResolverMatch есть args, список позиционных аргументов, и kwargs, список ключевых аргументов (которые можно создать с помощью именованных групп захвата ).

1 голос
/ 13 января 2012

Для регулярных выражений в общем случае скобки () указывают, что часть строки, которая соответствует регулярному выражению внутри скобок (в данном случае (\d{1,2})), является захваченной .

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

Это обычно используется в (например) операциях поиска / замены: скажем, я хотел включить «Я39 лет "на" Фуу, тебе 39! "Мы должны не только сопоставить I am xx years old, но также захватить 39, чтобы мы могли использовать его позже.

Как правило, тогда вы могли бы найти /заменить находкой I am (\d{1,2}) years old и заменить Ewww, you're \1!.Скобки в выражении поиска означают «сохранить все, что находится в этих скобках, потому что мы хотим использовать это позже», а \1 в выражении замены означает «положить первое, что мы сохранили здесь».

Для Django (r'some.regex.here.including.parentheses',FUNCTION) означает, что все, что сохранено (т.е. заключено в квадратные скобки) в регулярное выражение, передается в качестве аргумента функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...