你能从Django书的第3章(它是关于视图,网址模式和正则表达式)解释这个简单的例子吗?

时间:2012-01-13 01:42:59

标签: regex django django-views django-urls

我正在尝试按照此处的说明进行操作:http://www.djangobook.com/en/2.0/chapter03/(这个令人困惑的例子大约是页面下方的4/5)。

我们的想法是建立一个网址,其中/time/plus/1/time/plus/2/time/plus/3等中的任何一个 - 一直到/time/plus/99 - 都可以匹配。这本书说:

  

然后我们如何设计我们的应用程序来处理任意时间   偏移?关键是使用通配符URL模式。正如我们提到的   以前,URLpattern是一个正则表达式;因此,我们可以使用   正则表达式模式\ d +匹配一个或多个数字:

由于我们希望在99处停止,因此本书建议使用以下内容:

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

但是现在我们面临的问题是正确捕获正则表达式匹配的数字并在计算中使用它。这本书的解释继续:

  

现在我们已经为URL指定了通配符,我们需要一种方法   将那个通配符数据传递给view函数,这样我们就可以使用了   任意小时偏移的单一视图功能。我们这样做   在我们想要的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 个答案:

答案 0 :(得分:2)

正如您在问题中所提到的那样,括号形成了所谓的正则表达式capturing group

我没有在我面前使用Django代码,但您实际上可以使用re模块和asterisk来执行此类操作。

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:如果您感兴趣,here(第195-209行)是从URL路径捕获正则表达式的特定Django代码:

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,一个关键字参数列表(可以通过named capturing groups创建)。

答案 1 :(得分:1)

对于一般的正则表达式,括号()表示字符串中与括号内的正则表达式匹配的部分(在本例中为(\d{1,2}))是捕获的。 / p>

通过捕获,我的意思是保存它以便以后可以检索。

这通常用于(例如)查找/替换操作:说我想把“我39岁”改为“Ewww,你是39岁!”。我们不仅要匹配 I am xx years old,还要捕获 39以便我们以后可以使用它。

通常情况下,您可以使用I am (\d{1,2}) years old找到查找/替换,并替换为Ewww, you're \1!。 find表达式中的括号表示“保存这些括号中的任何内容,因为我们希望稍后使用它”,并且替换表达式中的\1表示“将我们保存的第一个内容放回到此处。”

对于Django,(r'some.regex.here.including.parentheses',FUNCTION)表示正则表达式中保存(即括号括起)的任何内容都作为参数传递给函数。