django project&#39 urls.py和views.py之间的联系

时间:2014-05-11 10:38:56

标签: python django django-urls

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)

urls.py

from django.conf.urls.defaults import *
from mysite.views import hello, current_datetime, hours_ahead

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

它表示参数偏移从匹配的url中提取的值不关心它的名称,但位置很重要。这是它在决定它能做什么之后的第二个参数。 但为什么 ? hours_ahead,只是一个用户定义的方法,而不是类或其他东西。谁赋予它能力,使参数的位置可以这样工作。 所以要明确,我的问题是,“offset = int(offset)”是否有任何意义,为什么偏移量可以在用户设置小时数时从url接收值。

2 个答案:

答案 0 :(得分:1)

它的工作方式是Django读取这个url模式r'^time/plus/(\d{1,2})/$',提取括号中的参数(在这种情况下为(\d{1,2})),然后将其作为参数传递给{{ 1}}功能。如果有许多参数,则在url模式中写入它们的顺序也决定了它们被传递到相应视图函数的顺序。您可以在此处详细阅读文档:https://docs.djangoproject.com/en/dev/topics/http/urls/

答案 1 :(得分:0)

  

它表示从匹配的url中提取的值的参数offset   不关心它的名字,但位置很重要。这是它的第二个   参数站在请求之后决定它能做什么。但为什么呢?

在Python中,您可以将两种参数传递给方法。位置参数和关键字参数。位置参数基于方法签名中的位置,它们的顺序很重要(这就是为什么它们被称为位置,因为它们在方法签名中的位置很重要。)

位置参数必须始终具有值。它们不是可选的。

关键字参数是可以按任何顺序传递的参数 - 只要它们在位置参数之后传入即可。关键字参数可以是可选的。

以下是一个例子:

def foo(a, b, c='Hello', d='World'):
    print(a,b,c,d)

ab是位置参数。它们是必需的。您必须传入一个值。 cd是可选的关键字参数,具有默认值。

传递的第一个参数将由a引用,第二个b引用。之后,您可以传递d,或c或无:

>>> foo(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes at least 2 arguments (1 given)
>>> foo(1,2)
(1, 2, 'Hello', 'World')
>>> foo(1,2,d='Yes')
(1, 2, 'Hello', 'Yes')
>>> foo(1,2,d='Yes',c='No')
(1, 2, 'No', 'Yes')

现在,在django的urls.py中 - 有两种方法可以捕获URL的元素:

^time/plus/(\d+{1,2})/$ - 这是捕获参数并将其作为位置参数传递。捕获的正则表达式的结果将传递给映射请求函数的第二个参数,无论该参数被调用(第一个参数通常称为 request )。

要映射上面的url,你必须有一个view方法,它只需要两个位置参数,但是你可以随意调用它们。请记住, request 是第一个位置参数。现在考虑到这一点,请考虑一下:

def foo(request, a) # You must have two positional arguments
def foo(request, b) # It does not matter what the second argument is called
def foo(request, a, b='world') # You can have any number of
                               # additional keyword arguments
                               # but they must be optional (have defaults)

def foo(request, a, b, c='world') # This will fail because you have two
                                  # positional arguments, but only one pattern is
                                  # captured in the URL.

^time/plus/(?P<offset>\d+{1,2})/$ - 此语法(称为命名组)将正则表达式的结果作为关键字参数传递给映射的URL函数。这意味着,2位数的值将作为关键字参数 offset 传递给视图函数。您可以在django documentation

中详细了解网址中的命名组

如果您具有上述命名的组URL模式,那么您的请求方法应具有以下签名:

def hours_ahead(request, offset)

例如,请考虑以下网址格式:

^time/(\d+{1,2})/(\d+{1,2})/(?P<hello>\w+)/$

要匹配此模式,您的视图函数必须具有以下签名:

def foo(request, a, b, hello)

当您收到以下网址time/32/42/world/时,a将为32,b将为42,hello将具有值世界。

如果您将视图方法中的hello更改为其他内容,例如def foo(request, a, b, blah)您的网址将无法映射,因为该模式专门在寻找关键字hello 功能签名。