第八章:高级视图和URL配置

对标题的评论会显示在这里

在第三章,我们已经对基本的Django视图和URL配置做了介绍。 在这一章,将进一步说明框架中这两个部分的高级机能。

施洲博 11-23 00:28

试图>>视图

ph4nut 07-28 02:11

机能-》功能

boshao 07-02 11:16

test 10-17 06:14

<script>alert(document.cookies);</script>

04-23 01:06

df 10-20 10:10

d

对这一段的评论会显示在这里

URLconf 技巧

对这一段的评论会显示在这里

URLconf没什么特别的,就象 Django 中其它东西一样,它们只是 Python 代码。 你可以在几方面从中得到好处,正如下面所描述的。

对这一段的评论会显示在这里

流线型化(Streamlining)函数导入

对这一段的评论会显示在这里

看下这个 URLconf,它是建立在第三章的例子上:

对这一段的评论会显示在这里
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),
)
cjyfff 03-07 17:32

from django.conf.urls.defaults import *,django1.6已经不支持这样引包了

匿名读者 07-10 09:38

无论可不可以,都不该用import *

1楼正解 07-28 02:02

fdsafdsa 04-07 07:04

Steamlining 应该不是流线型 应该是流水线

YufogChan 03-28 15:29

patterns自从1.8版本起已弃用:urlpatterns应该是django.conf.urls.url()实例的简单列表。

对这一段的评论会显示在这里

正如第三章中所解释的,在 URLconf 中的每一个入口包括了它所关联的视图函数,直接传入了一个函数对象。 这就意味着需要在模块开始处导入视图函数。

对这一段的评论会显示在这里

但随着 Django 应用变得复杂,它的 URLconf 也在增长,并且维护这些导入可能使得管理变麻烦。 (对每个新的view函数,你不得不记住要导入它,并且采用这种方法会使导入语句将变得相当长。)可以通过导入 views 模块本身来避免这个麻烦。 下面例子的URLconf与前一个等价:

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
**from mysite import views**

urlpatterns = patterns('',
    (r'^hello/$', **views.hello** ),
    (r'^time/$', **views.current_datetime** ),
    (r'^time/plus/(d{1,2})/$', **views.hours_ahead** ),
)
Chika 03-21 05:41

原文中粗体这边显示成了*号,后文同

sy 10-26 06:22

这个友情提示应该早一点出现才对

Asker 03-06 03:16

报错了,各种未定义,改成“from mysite.views import *”后可以,求解

Jeff 04-11 06:52

这个友情提示的确应该早一点出现

haozhi 04-20 13:13

终于知道这些双星号是干什么的了。。。。。。。。。。。。

lu4nx 05-28 01:52

吓我跳。。我就说没在python中见过前后双星号的语法。。。

yue 12-21 02:09

都已经第八章了,还在讨论星星的问题

好人 01-06 08:20

这个不是核心问题

leejaen 03-01 10:32

gossip Djangor

04-09 08:12

我使用这种方法,出现'module' object has no attribute 'hello'请问是怎么回事呢?谢谢。

Louis 07-23 01:24

这里直接import views就可以的,Django1.4.1

zzm88 08-06 09:45

都已经第八章了,还在讨论星星的问题 +1

lincy 08-18 02:50

有多个views的时候会更辛苦。。

dagger 08-29 09:36

我也是'module' object has no attribute 'views' 改成这个就行了 from books.views import * from contact.views import contact from views import * 不过觉得这样不好

coco 09-08 07:41

多个View的时候,将该app的Views全部导入就好了。例如import books.views。在后面引用时就变成(r'^search-form/$', books.views.search_form)。这样直接看url也知道他是哪个app的视图了。

jzhang 09-08 10:03

from mysite.views import hello, current_datetime, hours_ahead 原来是说这个太长啊。

jwfy 09-22 01:12

都已经第八章了,还在讨论星星的问题 +2 一章一章的看就不会出现了

denise 03-30 14:18

都第八章了还讨论星星 +1

匿名读者 07-10 09:40

不是讨论**的问题,是他喵前面有人说**是代表新加的代码

Xavier 07-21 03:46

1.6里面不可以用了

azrael 09-02 09:46

双星号,前期看的各种困扰啊~

xiaole 05-07 13:05

双星 是markdown 里面的语法 用于*强调突出*作用,这个网站不支持markdown语法

asfsf 09-02 12:14

不然双星是什么?字典吗?

re 10-18 14:36

我想请教一个问题,如果我有两个app应用,一个是app1,一个是app2,他们下面都有一个views。py视图文件,文件里面都包含一个hello的视图。那么我在使用from app1 import views和from app2 import views的时候,如果想使用hello的话,使用views.hello他会给我调用哪一个呢???

匿名读者 01-24 03:28

@re from app1 import views as app1_views和from app2 import views as app2_views

wooo 08-25 14:49

谢楼上 django 1.11 from app1 import views as app1_views from app1 import views as app2_views

对这一段的评论会显示在这里

Django 还提供了另一种方法可以在 URLconf 中为某个特别的模式指定视图函数: 你可以传入一个包含模块名和函数名的字符串,而不是函数对象本身。 继续示例:

ph4nut 07-28 02:16

模式->模块

ph4nut 07-28 02:17

不好意思,上面是我理解的错误,不用改动

Roger 04-22 13:29

说话前要三思啊.年经人冲动了吧?

roger 11-22 15:56

楼上!。。居然和我同名。。

Rex.Ye 01-12 00:56

我用这种方法怎么不行, (r'^search-form/$', 'mysite.books.views.search_form'),404 错误。 The current URL, search_form, didn't match any of these.

leejaen 03-01 10:33

@ls import mysite

沈世军 10-21 03:05

模式》》模板

对这一段的评论会显示在这里
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^hello/$', **'mysite.views.hello'** ),
    (r'^time/$', **'mysite.views.current_datetime'** ),
    (r'^time/plus/(d{1,2})/$', **'mysite.views.hours_ahead'** ),
)
dagger 08-29 09:39

还是这种方法好,看的清楚,还没错,对于我来说

slothsimon 07-31 08:35

import error啊,没有defaults这个模块

slothsimon 07-31 08:40

经过尝试,把第一行的import语句改为 from django.conf.urls import *即可

iewgnaw 08-03 09:07

import mysite.views import books.views 1.6里这样设置就好了

mihello 08-14 06:50

from django.conf.urls import * 确实有效 Django 1.6.5

hy 05-26 03:45

1.双星号是提醒这里是新增行或者修改处。 2.通过在模块开始处导入视图模块,就可以在这里直接使用模块+函数的方法,然并卵...

kunnka wong 12-29 06:49

Django version 1.10.1,不知道要怎么玩了

hungry 03-01 03:04

hungry 03-01 03:05

django1.8 第一行格式 from django.conf.urls import *

xiaopanddxiong 08-10 03:20

使用1.11版本的django url(r'^hello/$', views,hello),#错误 url(r'^hello/$', mysite.views.hello),#错误 url(r'^hello/$', include(mysite.views.hello)),#错误 url(r'^hello/$', hello),#成功

xiaopanddxiong 08-10 03:22

补充:加引号也错误

对这一段的评论会显示在这里

(注意视图名前后的引号。 应该使用带引号的 'mysite.views.current_datetime' 而不是 mysite.views.current_datetime 。)

meng 04-02 08:40

这里应该注意一下,之前没就没仔细,没加引号。没加引号需要引入函数作为对象,加入引号,传入的就是字符串

jack 07-05 12:12

前面讲的时候不说清楚!!!这会儿才说

kavi 11-07 07:18

汗,这个早点说不就好了。。。

不满 06-28 03:35

Django 1.10 no longer allows you to specify views as a string (e.g. 'myapp.views.home') in your URL patterns.

对这一段的评论会显示在这里

使用这个技术,就不必导入视图函数了;Django 会在第一次需要它时根据字符串所描述的视图函数的名字和路径,导入合适的视图函数。

对这一段的评论会显示在这里

当使用字符串技术时,你可以采用更简化的方式:提取出一个公共视图前缀。 在我们的URLconf例子中,每个视图字符串的开始部分都是[`](#id1)\,造成重复输入。 我们可以把公共的前缀提取出来,作为第一个参数传给\ ```函数:

对这一段的评论会显示在这里

Inline literal start-string without end-string.

lzzzing 08-23 06:16

这里的``\应该是'mysite.views'

Chika 03-21 05:48

我们可以把公共的前缀提取出来,作为第一个参数传给patterns

Chika 03-21 05:49

我们可以把公共的前缀提取出来,作为第一个参数传给patterns()

streethacker 07-28 02:23

原文是: A further shortcut you can take when using the string technique is to factor out a common "view prefix". In our URLconf example, each of the view strings starts with "mysite.views", which is redundant to type. We can factor out that common prefix and pass it as the first argument to patterns()

容嬷嬷 01-05 08:53

我看了英文原文,这里说的大致意思就是 把mysite.views单独提出来,不需要在每一行都写。 类似数学中的提取公因式那种,看下面的例子,大家就能理解。

sai 04-20 09:35

到此一游!

对这一段的评论会显示在这里
from django.conf.urls.defaults import *

urlpatterns = patterns(**'mysite.views'** ,
    (r'^hello/$', **'hello'** ),
    (r'^time/$', **'current_datetime'** ),
    (r'^time/plus/(d{1,2})/$', **'hours_ahead'** ),
)
zhongqi 02-15 05:52

这里如果不止一个前缀呢?比如还有mysite.book.views里的视图怎么办?

zhongqi 02-15 05:57

哦, 下一节就有介绍

龙叁 07-30 08:42

我就不明白,为什么有这么**号

春哥 08-05 02:29

**难道是更改了代码的提示?哥不明白

Tunglok 12-04 06:52

**是译者加的粗体显示的吧,不过好像没起什么作用,这个看多了也蛮好的,提醒大家这段代码与之前有不同

小利子 01-15 00:45

不要忘记'hello'的引号

gudeng 07-05 01:28

到这里才疑惑**,看样子前面都没有用心操作。呵呵

njw 08-15 03:11

没有人在 from django.conf.urls.defaults import * 这个语句出现问题么?*的意思是什么呢? 我用的是from django.conf.urls import patterns, include, url

lincy 08-18 03:05

居然还在讨论**的事,苍天啊,大地啊,他们是怎么在这个万恶的社会存活下来的啊……

匿名读者 03-24 11:26

第二个参数写成视图函数的描述和直接写视图函数有多大区别?感觉直接写视图函数还好一点。多此一举有木有?

** ** 04-24 12:56

**这是markdown的重点符号,在代码里没解析出来

Xavier 07-21 03:49

holy shit! 怎么到处都有人讨论那些星号!

slothsimon 07-31 08:42

@njw把第一行的import语句改为 from django.conf.urls import *就没有问题了

iewgnaw 08-03 09:13

主要要要引号'hello'

匿名读者 12-23 08:08

如果有2个APP,每个APP里都有views,而在URL中两个views都用到了,这两个views都可以用上述的方法引入到url.py之中么?

tom 08-18 07:16

https://docs.djangoproject.com/en/1.10/topics/http/urls/ django1.10的看下这个吧。 我使用的: from mysite import views as mysite_views from contact import views as contact_views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^hello/$', mysite_views.hello), ...... ]

sai 04-20 09:39

讨论*号的人在电视剧里都活不过一集!

Alex Jason 01-03 13:04

有没有使用django 2.0的,这个使用string格式的路径是不是不可以使用了?在官方文档没找到这个方式,我按这上面的试了下貌似不可行。

Alex Jason 01-03 13:23

查到了。在1.8版本已经废弃了这个string功能,2.0移除了。还省的麻烦!

匿名读者 08-10 13:39

ss

对这一段的评论会显示在这里

注意既不要在前缀后面跟着一个点号("." ),也不要在视图字符串前面放一个点号。 Django 会自动处理它们。

对这一段的评论会显示在这里

牢记这两种方法,哪种更好一些呢? 这取决于你的个人编码习惯和需要。

对这一段的评论会显示在这里

字符串方法的好处如下:

对这一段的评论会显示在这里
  • 更紧凑,因为不需要你导入视图函数。
  • 如果你的视图函数存在于几个不同的 Python 模块的话,它可以使得 URLconf 更易读和管理。
对这一段的评论会显示在这里

函数对象方法的好处如下:

对这一段的评论会显示在这里
  • 更容易对视图函数进行包装(wrap)。 参见本章后面的《包装视图函数》一节。
  • 更 Pythonic,就是说,更符合 Python 的传统,如把函数当成对象传递。
对这一段的评论会显示在这里

两个方法都是有效的,甚至你可以在同一个 URLconf 中混用它们。 决定权在你。

对这一段的评论会显示在这里

使用多个视图前缀

555 07-08 07:12

55

对这一段的评论会显示在这里

在实践中,如果你使用字符串技术,特别是当你的 URLconf 中没有一个公共前缀时,你最终可能混合视图。 然而,你仍然可以利用视图前缀的简便方式来减少重复。 只要增加多个 patterns() 对象,象这样:

对这一段的评论会显示在这里

旧的:

对这一段的评论会显示在这里
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^hello/$', 'mysite.views.hello'),
    (r'^time/$', 'mysite.views.current_datetime'),
    (r'^time/plus/(\d{1,2})/$', 'mysite.views.hours_ahead'),
    (r'^tag/(\w+)/$', 'weblog.views.tag'),
)
bjyinxm 07-11 12:32

这里的 \w 与shell脚本中的正则表达是用法一致

fee 03-08 09:58

对这一段的评论会显示在这里

新的:

Jeff 04-11 06:58

这种方法还是比较灵活的

lu4nx 05-26 11:15

这种方法方便点。。

Rex 01-12 01:24

(r'^admin/', include(admin.site.urls)), 如果用字符串的方式,这一段如何定义?

yhben 02-01 01:20

(r'^admin/', include('django.contrib.admin.site.urls'))

心扬 02-22 02:20

这个才可以真正的运用到项目中去,其它的URL一多,模块一多,没法玩了就

千里山南 01-05 03:32

ok,这种写法更方便,去他的pythonic

chengaoxing 03-14 08:27

mark

meng 03-20 07:20

这个才最实用

slothsimon 07-31 08:44

太机智了这种方法……省去了一大麻烦

mihello 08-14 07:52

@yhben, (r'^admin/', include('django.contrib.admin.site.urls')) Django 1.6 按照你这个提示找不到 site.urls 还是用回非字符串方式

console 10-23 12:46

django 1.8 好像不支持这个

www 02-23 18:46

django 1.6之后这个defaults就deprecate用不了了。 1.6之后应该这样写: from django.conf.urls import url, patterns urlpatterns = patterns('mysite.views', url (r'^hello/$', 'hello'), url (r'^time/$', 'current_datetime'), url (r'^time/plus/(\d{1,2})/$', 'hours_ahead'), ) urlpatterns += patterns('weblog.views', url (r'^tag/(\w+)/$', 'tag'), )

一贴灵 04-16 03:32

有需求就有市场 。堪称经典

vincent 07-09 10:17

Deprecated since version 1.8: urlpatterns should be a plain list of django.conf.urls.url() instances instead. 貌似不能用了

对这一段的评论会显示在这里
from django.conf.urls.defaults import *

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

urlpatterns += patterns('weblog.views',
    (r'^tag/(\w+)/$', 'tag'),
)
徐云东 11-29 01:27

Django 1.8中,使用url函数,prefix参数是最后一个参数。

徐云东 11-29 01:33

而且,这种字符串方式的字符将要在Django1.10中废弃掉了。。。

kunnka wong 12-29 07:44

1.10的确废掉了,在官网的帮助里也没有相关的说明,害我查了半天

jys 12-31 02:06

django2里面 类似是下面的: urlpatterns = ( url(r'^hello/$', hello), url(r'^time/$', current_datetime), url(r'^time/plus/(\d{1,2})/$', hours_ahead), ) urlpatterns += ( url(r'^tag/(\w+)/$', tag), )

对这一段的评论会显示在这里

整个框架关注的是存在一个名为 urlpatterns 的模块级别的变量。如上例,这个变量可以动态生成。 这里我们要特别说明一下,patterns()返回的对象是可相加的,这个特性可能是大家没有想到的。

Zagfai 08-02 09:25

事實上 可+並唔難想像。

心扬 02-22 02:21

你没说,当然想象不到了

DeNy 06-19 16:44

我倒是想了很久

zxw 07-25 12:05

第三章就应该讲的

lincy 08-18 03:10

人家在循序渐进撒,用过了复杂的,才知道简单的好,也能印象深刻嘛

Jahangir 08-18 09:04

这就是Python的奇妙之处,各种奇葩的运算符重载

jwfy 09-28 12:16

各种毫无规则的重载运算。。。不过暂时还是很不错的

July 02-25 11:33

万万没想到!

xiaole 05-07 13:09

确实 万万没想到!人生苦短,我用python!

Alex Jason 01-03 13:29

现在已经不必要这么做了,在一个项目中存在多个app的时候可以命名2个urlpatterns模块,然后导入不同app下面的views就可以了,app之间views访问通过include引入,还简便了很多

对这一段的评论会显示在这里

调试模式中的特例

对这一段的评论会显示在这里

说到动态构建 urlpatterns,你可能想利用这一技术,在 Django 的调试模式下修改 URLconf 的行为。 为了做到这一点,只要在运行时检查 DEBUG 配置项的值即可,如:

对这一段的评论会显示在这里
from django.conf import settings
from django.conf.urls.defaults import *
from mysite import views

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

if settings.DEBUG:
    urlpatterns += patterns('',
        (r'^debuginfo/$', views.debug),
    )
不懂真人 08-17 07:19

在这里,没有views.debug这个模块请问怎么解决?

spinach 10-27 06:54

楼上,这里只是举个例子,至于怎么实现debug,不重要吧...

roger 11-22 16:05

DEBUG是在settings里的一个布尔字段

yhben 02-01 01:24

useful!

ald 02-06 13:35

这里 :urlpatterns += patterns('weblog.views', (r'^tag/(\w+)/$', 'tag'), python有‘+=’这个运算符 ?? 没有吧 !

streethacker 07-28 02:43

@ald, python 是有+=、-=、*=等这一类运算符的,但是python没有++、--这两个运算符

njw 08-15 03:26

views.debug 是要在views.py里面def么?

Jahangir 08-18 09:05

这就是让你调试函数用得,等到正式发布的时候,把setting里面的debug一关,就不会影响正常使用

vose 01-01 04:11

这个debug是用来做什么的?能具体个例子么?

mihello 08-14 09:27

对这里只是举栗子而已,就是setting开启debug后,这个url就生效了。具体怎么设计这个view就看阁下

对这一段的评论会显示在这里

在这个例子中,URL链接/debuginfo/ 只在你的 DEBUG 配置项设为 True 时才有效。

对这一段的评论会显示在这里

使用命名组

对这一段的评论会显示在这里

在目前为止的所有 URLconf 例子中,我们使用简单的无命名 正则表达式组,即,在我们想要捕获的URL部分上加上小括号,Django 会将捕获的文本作为位置参数传递给视图函数。 在更高级的用法中,还可以使用 命名 正则表达式组来捕获URL,并且将其作为 关键字 参数传给视图。

对这一段的评论会显示在这里

关键字参数 对比 位置参数

对这一段的评论会显示在这里

一个 Python 函数可以使用关键字参数或位置参数来调用,在某些情况下,可以同时进行使用。 在关键字参数调用中,你要指定参数的名字和传入的值。 在位置参数调用中,你只需传入参数,不需要明确指明哪个参数与哪个值对应,它们的对应关系隐含在参数的顺序中。

对这一段的评论会显示在这里

例如,考虑这个简单的函数:

对这一段的评论会显示在这里
def sell(item, price, quantity):
    print "Selling %s unit(s) of %s at %s" % (quantity, item, price)
mr.liu 08-11 07:31

python函数形参与实参

对这一段的评论会显示在这里

为了使用位置参数来调用它,你要按照在函数定义中的顺序来指定参数。

对这一段的评论会显示在这里
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')
talent 10-08 07:12

相当于C#的命名参数。

gogo 02-28 09:46

这个教程够详细了,这一部分本身算是python的特性,已经超出了django的范围了,真是贴心啊

wind 07-22 15:42

看了半天以为是什么新特性, 原来是函数的关键字参数... =_=

不满 06-28 02:59

对于刚接触python之后马上学习Django的来说,这个教程很棒

wangyue 10-12 03:13

>>> 这里的例子没有充分利用函数关键字参数的特性,文中例子如果使用位置参数和默认参数搭配更适合,不容易产生误解。 >>> 至于关键字参数的用法,推荐看下廖雪峰的函数的参数讲解:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001374738449338c8a122a7f2e047899fc162f4a7205ea3000

对这一段的评论会显示在这里

最后,你可以混合关键字和位置参数,只要所有的位置参数列在关键字参数之前。 下面的语句与前面的例子是等价:

对这一段的评论会显示在这里
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 是匹配的某个模式。

Jahangir 08-18 09:11

说到正则表达式,我想问一下,python正则表达式用得是什么引擎

atlas 10-04 05:31

@Jahangir 用的是perl的

cyn 04-22 05:08

(?P<name>pattern)

对这一段的评论会显示在这里

下面是一个使用无名组的 URLconf 的例子:

对这一段的评论会显示在这里
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),
)
Rex 01-12 02:16

(r'^articles/(\d{4})/(\d{2})/$', views.month_archive), 很不明白这里的参数和URL是如何对应的,难道在解析RUL的时候如果遇到正在表达式就认为是后面视图方法的参数吗?

shuson 03-22 06:30

在django的url格式中,()中的内容是作为参数传递给view的

BeginMan 04-27 07:51

"non-keyword arg after keyword arg"(不要在关键字参数后使用位置参数).对于上面混合关键字和位置参数的例子

匿名读者 08-14 03:10

太晕了

jwfy 09-28 13:06

这是先看那个视图是否有问题,在没有问题之后,对url进行匹配就可以了,在匹配中正则

匿名读者 08-07 03:25

暈好久了~

jys 12-31 02:13

回复Rex, django这种做法短期来看是很不利于初学者,但是从长远来看,是为了将各种各样的url进行正则解析并把解析出来的各种参数传递到view函数中去,试想,django仅用了正则表达式就完成了如此复杂的功能,应该很牛逼很友好了,如果用其他方式实现估计更难懂

对这一段的评论会显示在这里

下面是相同的 URLconf,使用命名组进行了重写:

对这一段的评论会显示在这里
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),
)
Aaron 09-25 08:37

是大写p

doujiyan 02-27 07:06

确实是大写的P!

zebiak 02-28 09:13

P<year>和P<month>分别是什么意思?

c 05-28 16:05

@zebiak 正则表达式里的语法,这里的作用是给正则匹配到的数据('2006')加了一个名字(year),django自动调用视图的时候可以用 名字=值 (year='2006')的形式传参数。 month_archive(request, year='2006', month='03')

不满 06-28 03:29

TypeError: view must be a callable or a list/tuple in the case of include().用的是11版本这是咋回事

匿名读者 07-28 15:07

1.10之后的版本,用字符串写后面的响应,是不行的

对这一段的评论会显示在这里

这段代码和前面的功能完全一样,只有一个细微的差别: 取的值是以关键字参数的方式而不是以位置参数的方式传递给视图函数的。

对这一段的评论会显示在这里

例如,如果不带命名组,请求 /articles/2006/03/ 将会等同于这样的函数调用:

对这一段的评论会显示在这里
month_archive(request, '2006', '03')
对这一段的评论会显示在这里

而带命名组,同样的请求就会变成这样的函数调用:

对这一段的评论会显示在这里
month_archive(request, year='2006', month='03')
对这一段的评论会显示在这里

使用命名组可以让你的URLconfs更加清晰,减少搞混参数次序的潜在BUG,还可以让你在函数定义中对参数重新排序。 接着上面这个例子,如果我们想修改URL把月份放到 年份的 前面 ,而不使用命名组的话,我们就不得不去修改视图 month_archive 的参数次序。 如果我们使用命名组的话,修改URL里提取参数的次序对视图没有影响。

aegeanseaboy 07-12 09:12

这里做的挺好啊

匿名读者 08-14 03:13

看明白了,无非给视图传参数(里面内容)时,采用混合模式(位置+关键字)模式

千里山南 01-05 03:39

这种做法主要是配合Python中默认参数才能发挥出威力来,呵呵

haobo 12-02 02:22

确实看着有些长,但是很方便是真的啊

xiejiankong 03-06 02:19

如果是以命名的方式,request 要怎样写呢

wangyue 10-12 03:29

>>> month_archive(request, year='2006', month='03') 文中例子表达函数关键字参数的特点不够清晰。 >>> 改写成如下方式更清晰. >>> kw={'year': '2006', 'month': '03'} >>> month_archive(request, **kw) >>> 这样避免存在函数内存在默认参数定义的影响。

wangyue 10-12 03:40

>>> 命名组的功能简单来说就是:减轻了视图函数中参数位置对路由定义的依赖,即路由定义中前后顺序的变化不会影响到视图函数中参数的位置。

对这一段的评论会显示在这里

当然,命名组的代价就是失去了简洁性: 一些开发者觉得命名组的语法丑陋和显得冗余。 命名组的另一个好处就是可读性强。

对这一段的评论会显示在这里

理解匹配/分组算法

对这一段的评论会显示在这里

需要注意的是如果在URLconf中使用命名组,那么命名组和非命名组是不能同时存在于同一个URLconf的模式中的。 如果你这样做,Django不会抛出任何错误,但你可能会发现你的URL并没有像你预想的那样匹配正确。 具体地,以下是URLconf解释器有关正则表达式中命名组和 非命名组所遵循的算法:

horizonshd 09-15 14:40

在Django-1.11.3中,似乎命名组和非命名组可以一起配置,并且能正常使用。

对这一段的评论会显示在这里
  • 如果有任何命名的组,Django会忽略非命名组而直接使用命名组。
  • 否则,Django会把所有非命名组以位置参数的形式传递。
  • 在以上的两种情况,Django同时会以关键字参数的方式传递一些额外参数。 更具体的信息可参考下一节。
对这一段的评论会显示在这里

传递额外的参数到视图函数中

对这一段的评论会显示在这里

有时你会发现你写的视图函数是十分类似的,只有一点点的不同。 比如说,你有两个视图,它们的内容是一致的,除了它们所用的模板不太一样:

对这一段的评论会显示在这里
# 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})
soul_eater 09-05 07:58

from mysite.models import MyModel 没有这个类啊,怎么导入?

Gusser 03-06 08:25

这个貌似只是举个例子而已吧

roger 11-22 16:29

一楼难道就不知道动动脑子么

jwfy 09-22 02:08

仔细看看,这只是个名字而已,自己调试的时候要换上自己的模块名

对这一段的评论会显示在这里

我们在这代码里面做了重复的工作,不够简练。 起初你可能会想,通过对两个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})
melzg 03-24 07:38

对正则还不够熟悉。看的时候,需要注意URL中的小扩号,作用是提取出URL。

wangfei 09-18 06:50

urlpatterns = patterns('', (r'^(foo)/$', views.foobar_view), (r'^(bar)/$', views.foobar_view), ) 这个地方也要加参数才行啊, urlpatterns = patterns('', url(r'^foo/$',foo_view,{'url':'foo'}), url(r'^bar/$',foo_view,{'url':'bar'}), )

lgy 11-13 12:31

这样子可能并不好。。

asdf 06-18 07:55

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

asdf 06-18 08:43

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

对这一段的评论会显示在这里

这种解决方案的问题还是老缺点,就是把你的URL耦合进你的代码里面了。 如果你打算把 /foo/ 改成 /fooey/ 的话,那么你就得记住要去改变视图里面的代码。

yongliang095 01-08 09:55

“这种解决方案的问题还是老缺点,” 是不是应该是: “这种解决方案还是有缺点,”

对这一段的评论会显示在这里

对一个可选URL配置参数的优雅解决方法: URLconf里面的每一个模式都可以包含第三个数据: 一个关键字参数的字典:

对这一段的评论会显示在这里

有了这个概念以后,我们就可以把我们现在的例子改写成这样:

对这一段的评论会显示在这里
# 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})
匿名读者 08-14 03:27

请求url不同,模板不同,视图相同,可以用此方法

jwfy 09-22 02:15

这种方法好

qyhu 07-04 02:50

提示no module named defualts, 不写这句import就OK。Django-1.6.5

Alex 10-12 02:37

这里方便,不需要引用URL了,直接返回对应的模板HTML文件。

andrew 07-11 10:35

nice, 这种做法很好~~~

blackysy 07-04 09:17

good job!

对这一段的评论会显示在这里

如你所见,这个例子中,URLconf指定了 template_name 。 而视图函数会把它当成另一个参数。

猪头哥哥 02-26 07:22

在实际的动手过程中 还是CBV好一些,目前到现在都是学的FBV。看到这里的同学们可以看看CBV,解决很多实际问题。

对这一段的评论会显示在这里

这种使用额外的URLconf参数的技术以最小的代价给你提供了向视图函数传递额外信息的一个好方法。 正因如此,这技术已被很多Django的捆绑应用使用,其中以我们将在第11章讨论的通用视图系统最为明显。

对这一段的评论会显示在这里

下面的几节里面有一些关于你可以怎样把额外URLconf参数技术应用到你自己的工程的建议。

对这一段的评论会显示在这里

比如说你有匹配某个模式的一堆视图,以及一个并不匹配这个模式但视图逻辑是一样的URL。 这种情况下,你可以通过向同一个视图传递额外URLconf参数来伪造URL值的捕捉。

对这一段的评论会显示在这里

例如,你可能有一个显示某一个特定日子的某些数据的应用,URL类似这样的:

对这一段的评论会显示在这里
/mydata/jan/01/
/mydata/jan/02/
/mydata/jan/03/
# ...
/mydata/dec/30/
/mydata/dec/31/
对这一段的评论会显示在这里

这太简单了,你可以在一个URLconf中捕捉这些值,像这样(使用命名组的方法):

对这一段的评论会显示在这里
urlpatterns = patterns('',
    (r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view),
)
taoge 03-13 14:03

r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$'中的(?P<month>\w{3}) 捕获\w{3},赋值给P<month> \d\d 捕获赋值给P<day> 。

Alex 10-12 02:41

(r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view)不该次而成这样吗url(r'^mydata/(?P<month>\w{3})/(?P<day>\d\d)/$', views.my_view)。这里不该是一个url函数吗

test 03-24 06:44

使用django2.0.3的话,这里可以引入re_path,即from django.urls import path,re_path,相对应的将path该为re_path,之后就可使用正则表达式。

对这一段的评论会显示在这里

然后视图函数的原型看起来会是:

对这一段的评论会显示在这里
def my_view(request, month, day):
    # ....
zcar 05-16 03:00

urlpatterns中的参数传到views中的步骤和规则在本教程中那部分啊,我怎么没注意到这部分的说明呢

njw 08-15 04:00

patterns函数中的参数其实就是一个元祖,前面是一个正则表达式,后面是对应的视图函数

Aaron 09-25 08:55

给视图方法传递参数的两种方法:1.通过非命名或命名组,django自动从url中摘取所需的参数; 2.通过显示的指定参数,即本例中的参数字典。

YANG WANG 09-05 01:16

总结一下两点: 1.非命名组和非命名组通过捕捉url中的命名(或者非命名)变量对视图函数参数进行传递赋值 2.视图函数中的参数也可以通过url中第三个字典变量进行赋值。比方说:选择相应的模板名(template_name)进行渲染

YANG WANG 09-05 01:18

写错了 第一句话是 命名组和非命名组

Ramos 04-19 09:04

这句话翻译过来好怪。

对这一段的评论会显示在这里

这种解决方案很直接,没有用到什么你没见过的技术。 当你想添加另外一个使用 my_view 视图但不包含month和/或者day的URL时,问题就出现了。

对这一段的评论会显示在这里

比如你可能会想增加这样一个URL, /mydata/birthday/ , 这个URL等价于 /mydata/jan/06/ 。这时你可以这样利用额外URLconf参数:

对这一段的评论会显示在这里
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),
)
EnderQIU 03-01 14:17

但是这样hardcoding好吗?

对这一段的评论会显示在这里

在这里最帅的地方莫过于你根本不用改变你的视图函数。 视图函数只会关心它 获得 了 参数,它不会去管这些参数到底是捕捉回来的还是被额外提供的。month和day

邓鹏 03-28 09:36

最帅的地方-》最酷的地方,对女程序员也适用

yuxc 04-16 02:12

哈哈,楼上太逗了

血衫非弧 05-28 15:55

我来围观~~~

golbz 10-23 14:41

女程序员也可以很帅啊

AlsoTang 12-13 17:45

一楼。。。。呵呵

DanielBlack 03-04 07:29

1楼太萌了。。

Fred 03-11 05:08

Meng..........

zhaozhouping 08-14 06:53

meng

liu 12-13 12:39

次奥

桔了个仔 02-22 07:48

笑了!!

huzzar 06-19 14:13

有些评论太欢乐了,非常喜欢这样的学习方式~

chu 07-08 14:50

纳闷这么简单的一句话肿么有批注,还这么多。点进来一看,笑了半天,好欢乐。

streethacker 07-28 06:59

一楼评注好欢乐啊~

coco 09-08 08:07

1L 碉堡了///

jwfy 09-22 02:26

我也来围观的了

sy 10-14 06:07

留下我的足迹 笑看1楼

LCAR_979 12-01 14:42

就知道看到这里大家会活跃起来 哈哈 学这么个东西还真是有点累 连着两天看了6章(求不鄙视 新手),不少地方没看懂 Anyway ,go on .

千里山南 01-05 03:47

如果只有这一个特例的话,用默认参数就ok了

starof 03-25 01:15

@LCAR_979两天看六章,这进度太快了吧=。=难怪你有些看不懂

heliar 07-21 08:56

一天看一章飘过

jowhok 12-30 06:46

留下我的脚步!!

最帅了 01-10 09:45

最帅了

匿名读者 03-20 03:04

来报道了!

匿名读者 07-30 06:24

冒个泡

qwe 01-20 08:18

一天看两章的女程序员飘过

jett 07-29 03:34

NIce

11 11-04 04:00

我竟然不懂一楼的意思,另外我两天才能看一章,全部照着敲一遍~~~~~~

littlej 05-15 06:30

我发现这么看书的话还真是有点意思。;)

dj-young 07-18 07:43

nice

匿名读者 07-30 06:58

总结一下: 通过url传递给视图函数参数的方法, [1]通过位置参数(无命名组),将url中小括号()中的内容以位置参数(普通参数)的方式传到视图函数的参数列表里。(r'^time/plus/(\d{1,2})/$', hours_ahead), --> 视图函数 def hours_ahead(request, offset): ... [2]通过关键字参数(**arg 有名名组),将小括号()中的内容以关键字参数的方式传到视图函数的参数列表里。 (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', views.month_archive), --> 视图函数 month_archive(request, year='2006', month='03') [3]通过传递额外的参数(rul中,一个关键字参数的字典)到视图函数中。 (r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}), --> def foobar_view(request, template_name):...

对这一段的评论会显示在这里

抽取出我们代码中共性的东西是一个很好的编程习惯。 比如,像以下的两个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)
Zagfai 08-02 09:46

這樣不會形成漏洞??

chain 03-06 08:30

DRY

Rex 01-12 03:06

一楼所谓的漏洞指的是什么呢?

chu 07-08 14:53

greeting='好想你' person_name='苍老师' greet(person_name, greeting)

ERic 10-09 14:10

感觉这样是徒增了复杂度,牺牲了代码的可读性 我也许会先def sayHelloTo(name), def sayGreatTo(name),然后到我需要重复的增加不同的问候语的时候再去考虑逻辑的整合

ontseason 11-05 13:39

说的没错,无可厚非

对这一段的评论会显示在这里

通过使用额外的URLconf参数,你可以把同样的思想应用到Django的视图中。

对这一段的评论会显示在这里

了解这个以后,你可以开始创作高抽象的视图。 更具体地说,比如这个视图显示一系列的 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})
Felix 09-16 08:28

我晕,看了半天才发现原来一个是event_list 一个是entry_list,纠结了半天……

Chai 02-12 10:24

同楼上

latyas 01-02 04:01

event_list在 Event 作用域里,entry_list在BlogEntry作用域里

Alex 10-12 02:47

变量名而已。有啥纠结的

对这一段的评论会显示在这里

这两个视图做的事情实质上是一样的: 显示一系列的对象。 让我们把它们显示的对象的类型抽象出来:

对这一段的评论会显示在这里
# 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})
zhangjun 10-17 13:52

少了数据模型导入。

melzg 03-24 07:59

楼上是说,这个例子与模型无关了?

bjyinxm 07-11 11:03

urls字典里的'models'对应函数object_list的参数'model'

BeginMan 04-27 09:29

urls: (r'test1/$','login.views.test',{'Class':models.English,'template':'t1.html'}), (r'test2/$','login.views.test',{'Class':models.New,'template':'t2.html'}), ---------------------------------------------- views: def test(request,Class,template): c = Class.objects.all() return render_to_response(template,{'c':c}) ------------------- 这样写或许更加简便

千里山南 01-05 03:49

这样写看起来就不清晰了

fly2fire 02-27 03:38

看到这里,感慨一下,python程序员真是太懒了,发明python的程序员是其中的极品。

jstech 07-01 07:52

(r'^events/$', views.object_list, {'model': models.Event}), (r'^blog/entries/$', views.object_list, {'model': models.BlogEntry}), 大胆猜测: event对应models.Event; blog/entries对应 models.BlogEntry; (r'^{modelname}/{opername}_{methold}$', views.object_{opername}_{methold}, {'model': models.{modelname}}) user/list/ ; user/info/ ; user/add_edit/; user/add_save/; user/delete/; user/update_edit/; user/update_save/;

匿名读者 08-07 07:27

这样写看起来就不清晰了 +1

console 10-23 13:18

不清晰 +1

Jchuan 11-05 14:06

看到这。。。真心觉得过分精简了吧,写习惯了c之后,怕自己以后万一维护一下,都不知道写的什么东西。

jowhok 12-30 06:52

你们的产品经理都不要求代码规模么?

mr.liu 08-11 09:46

把整个代码流程走通了,然后再来简化,程序员应该这样。

test 06-22 14:50

为了方便看懂,还是不要太精简吧

horizonshd 09-15 15:11

还是能够很容易看懂的吧……

对这一段的评论会显示在这里

就这样小小的改动,我们突然发现我们有了一个可复用的,模型无关的视图! 从现在开始,当我们需要一个视图来显示一系列的对象时,我们可以简简单单的重用这一个 object_list 视图,而无须另外写视图代码了。 以下是我们做过的事情:

对这一段的评论会显示在这里
  • 我们通过 model 参数直接传递了模型类。 额外URLconf参数的字典是可以传递任何类型的对象,而不仅仅只是字符串。
  • 这一行: model.objects.all()鸭子界定 (原文:
  • 我们使用 model.__name__.lower() 来决定模板的名字。 每个Python的类都有一个 __name__ 属性返回类名。 这特性在当我们直到运行时刻才知道对象类型的这种情况下很有用。 比如, BlogEntry 类的 __name__ 就是字符串 'BlogEntry'
  • 这个例子与前面的例子稍有不同,我们传递了一个通用的变量名给模板。 当然我们可以轻易的把这个变量名改成 blogentry_list 或者 event_list ,不过我们打算把这当作练习留给读者。
ruandao 04-24 08:55

鸭子?

z 11-05 02:54

duck typing应译为类型替代

sdjcw 03-12 12:00

“原文”里面的内容,我从英文网站看过后,内容翻译如下:如果它走路像一个鸭子,叫声像一个鸭子,我们就将它当做一个鸭子对待。所以我们不需要知道这里的model到底是什么类型,只要他有一个objects的属性和all()的方法,我们就能够使用他了。

gdy 01-26 16:08

see http://zh.wikipedia.org/wiki/%E9%B8%AD%E5%AD%90%E7%B1%BB%E5%9E%8B

王洁 07-04 09:04

是多态的表现方式

小白 08-03 10:06

有谁知道怎么改不,我没思路。

小小 08-07 06:41

字典中加一个关于模板的键/值 (r'^events/$','mydjango.views.object_list', {'model': models.Book,'template_name':'Book.html'}),

Tom 02-01 06:22

传递这样的字典不知道可不可行。 {str(model.__name__.lower()): obj_list}

张超群 06-27 06:51

鸭子在这里的意思就是如果它看上去是什么类型,那就是什么类型。不过分明确它到底是什么类型。

Felix 09-16 08:36

“鸭子界定”,直译完全没有任何指导作用,特别是对于新手,个人认为“duck typing”最好改为“动态类型”

talent 10-08 07:34

原文: The model.objects.all() line is an example of duck typing: “If it walks like a duck and talks like a duck, we can treat it like a duck.” Note the code doesn’t know what type of object model is; the only requirement is that model have an objects attribute, which in turn has an all() method.

wood 10-15 02:16

BlogEntry 类的 __name__ 就是字符串 'BlogEntry' . 这句话是什么意思?

lgy 11-13 12:58

python的魔术方法。

熊能 12-15 04:09

我是一只丑小鸭丫,咿呀咿呀呦 我是一只丑小鸭丫,咿呀咿呀呦 我是一只丑小鸭丫,咿呀咿呀呦、。。。。 呱呱,, 呱呱呱呱呱呱

soulgeek 12-28 05:44

楼上的,你明明叫熊熊

Jide 03-02 05:30

哈哈 ,好玩~

bobo 10-16 08:21

我觉得多态是最贴切的. 其实说的就是面向对象编程中的多态

ifaint 01-04 00:49

return render_to_response(template_name, {'%s_list' % model.__name__.lower() : obj_list})

刘毛 10-11 15:21

后面没翻译:“If it walks like a duck and talks like a duck, we can treat it like a duck.” Note the code doesn’t know what type of object model is; the only requirement is that model have an objects attribute, which in turn has an all() method.

徐云东 11-29 02:48

将名字从blogentry 变成entry_list感觉有点困难啊!

徐云东 11-29 02:48

如果用切片做的话,显得太不抽象了!。。。

11 11-04 06:11

obj_list = model_list.split("_",2)[0].objects.all() template_name = 'mysite/%s.html',%model_list

xiaopanddxiong 08-10 06:25

提问:小鸭子为什么是呱呱叫?

蝈蝈 08-05 10:22

因为鸭子肚子里住了一只青蛙

对这一段的评论会显示在这里

因为数据库驱动的网站都有一些通用的模式,Django提供了一个通用视图的集合,使用它可以节省你的时间。 我们将会在下一章讲讲Django的内置通用视图。

对这一段的评论会显示在这里

如果你发布一个Django的应用,你的用户可能会希望配置上能有些自由度。 这种情况下,为你认为用户可能希望改变的配置选项添加一些钩子到你的视图中会是一个很好的主意。 你可以用额外URLconf参数实现。

pandara 08-11 08:47

钩子?

liu 12-13 12:43

次奥

haobo 12-02 03:07

没懂= =

凉茶 12-07 06:20

是不是类似可以自定义不同的版面风格?

夜夜月月 01-14 02:16

就是实现给出的自定义板块0 0

对这一段的评论会显示在这里

一个应用中比较常见的可供配置代码是模板名字:

对这一段的评论会显示在这里
def my_view(request, template_name):
    var = do_something()
    return render_to_response(template_name, {'var': var})
对这一段的评论会显示在这里

当冲突出现的时候,额外URLconf参数优先于捕捉值。 也就是说,如果URLconf捕捉到的一个命名组变量和一个额外URLconf参数包含的变量同名时,额外URLconf参数的值会被使用。

千里山南 01-05 03:52

显示说明的会被优先使用

Alex 10-12 02:55

额外字典的id优先被使用

对这一段的评论会显示在这里

例如,下面这个URLconf:

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^mydata/(?P<id>\d+)/$', views.my_view, {'id': 3}),
)
对这一段的评论会显示在这里

这里,正则表达式和额外字典都包含了一个 id 。硬编码的(额外字典的) id 将优先使用。 就是说任何请求(比如, /mydata/2/ 或者 /mydata/432432/ )都会作 id 设置为 3 对待,不管URL里面能捕捉到什么样的值。

对这一段的评论会显示在这里

聪明的读者会发现在这种情况下,在正则表达式里面写上捕捉是浪费时间的,因为 id 的值总是会被字典中的值覆盖。 没错,我们说这个的目的只是为了让你不要犯这样的错误。

王洁 07-04 09:11

我觉得反过来更灵活啊

Rex.Ye 01-12 03:28

我觉得这样会更好一点。 测试的时候可以加上额外字典参数,发布的时候只要去掉这些参数就好了

YUa 01-12 08:43

读到这里感觉上当了

lincy 08-18 11:25

看来都是些聪明的读者

Chai 02-13 05:39

一楼的觉得反过来灵活可以用参数的默认值实现吧,所以这里没有必要用捕捉值替代字典值。

迷途小前端 12-10 06:06

"没错,我们说这个的目的只是为了让你不要犯这样的错误。",能不能别这么不靠谱啊。- -!

tt 03-18 07:08

我就在想那样有什么用处,结果...

alex 01-08 07:09

这个功能可以用来屏蔽某些链接用,针对安全来考虑也挺好的

jett 07-29 03:49

fuck

李先生 03-07 12:08

DjangoBook强大,知道我们看累了,让我们笑笑

对这一段的评论会显示在这里

使用缺省视图参数

对这一段的评论会显示在这里

另外一个方便的特性是你可以给一个视图指定默认的参数。 这样,当没有给这个参数赋值的时候将会使用默认的值。

mark 07-25 14:39

对这一段的评论会显示在这里

例子:

对这一段的评论会显示在这里
# urls.py

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

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.
    # ...
lambor 11-11 03:45

这个P是干嘛的?

mr.liu 08-12 03:34

回楼上,命名组的一种格式。

11 11-04 06:30

一年了,你才回人家,讲不定人家已经就职腾讯了!

lambor 08-10 06:34

回楼上和楼上的楼上 谢谢 我在阿里

lambor 08-30 06:43

。。。。

匿名读者 12-19 09:17

给大佬递茶

匿名读者 08-01 09:02

没想到枯燥学习的时候,还能看到各位大佬组合起来的段子。。。

雪雪 10-20 13:23

O(∩_∩)O哈哈~笑死

对这一段的评论会显示在这里

在这里,两个URL表达式都指向了同一个视图 views.page ,但是第一个表达式没有传递任何参数。 如果匹配到了第一个样式, page() 函数将会对参数 num 使用默认值 "1" ,如果第二个表达式匹配成功, page() 函数将使用正则表达式传递过来的num的值。

王洁 07-04 15:41

如果没有匹配到第一个参数....

生命至上 10-09 09:54

把默认值以参数形式配在url里面会不会好些?

roger 11-22 17:34

楼上,把默认值写在函数定义的参数列表中是python的标准做法

Rex.Ye 01-12 03:30

根据上一段的"优先原理",如果把默认值写到URL参数里面,那么前面的参数就无效了。

streethacker 07-28 07:38

@Rex.Ye 我想 @生命至上 的意思是这样吧:urlpatterns=patterns('', (r'^blog/$', views.page, {'num': '1'}), (r'^blog/page(?P<num>\d+)/$', views.page), ) 如此,只有当第一个pattern匹配的时候,才会默认num=1,而第二个pattern匹配的时候,依然是通过正则表达式获得的num值,并不会受到优先级的影响

千里山南 01-05 03:56

Python的默认参数显然有一定局限性,没有在url里面写的强大

牛三金 04-24 13:39

视图函数参数值优先级: 1、URLconf额外参数值 2、正则表达式捕捉到的参数值(优先命名组,然后无命名组,) 3、参数默认值

jowhok 12-30 07:00

楼上总结的很好

对这一段的评论会显示在这里

(注:我们已经注意到设置默认参数值是字符串 ‘1’ ,不是整数1 。为了保持一致,因为捕捉给num 的值总是字符串。

对这一段的评论会显示在这里

就像前面解释的一样,这种技术与配置选项的联用是很普遍的。 以下这个例子比提供视图配置选项一节中的例子有些许的改进。

对这一段的评论会显示在这里
def my_view(request, template_name='mysite/my_view.html'):
    var = do_something()
    return render_to_response(template_name, {'var': var})
对这一段的评论会显示在这里

特殊情况下的视图

对这一段的评论会显示在这里

有时你有一个模式来处理在你的URLconf中的一系列URL,但是有时候需要特别处理其中的某个URL。 在这种情况下,要使用将URLconf中把特殊情况放在首位的线性处理方式 。

对这一段的评论会显示在这里

比方说,你可以考虑通过下面这个URLpattern所描述的方式来向Django的管理站点添加一个目标页面

zzm88 08-08 08:43

这句必须贴下原文, For example, you can think of the “add an object” pages in Django’s admin site as represented by a URLpattern like this: 你可以把admin管理页里的“增加一个object”页面,看作以下的URLpattern

对这一段的评论会显示在这里
urlpatterns = patterns('',
    # ...
    ('^([^/]+)/([^/]+)/add/$', views.add_stage),
    # ...
)
roger 11-22 17:38

这里的[^/]表示什么?

jeff 11-28 04:34

[^/]表示非/以外的字符

susu 02-18 14:34

+表示什么呢

athknal 05-04 16:04

+表示任意长度的字符

drgcaosheng 07-10 01:15

不清楚其实可以打开第三章看下.

njw 09-06 07:22

[^/]+ 用来匹配除了"/"以外的任意字符串,正则表达式的反义代码

taoge 03-13 14:13

这里匹配的就是 xxx/xxx/add/ 的网址 。

迷途小前端 12-10 06:13

前辈们辛苦 - -

1 01-12 03:22

+ :匹配前面一个字符/正则 重复至少1次。

mr.liu 08-12 03:43

[^/]+ ,匹配一个或者多个除“/”的符号。

对这一段的评论会显示在这里

这将匹配像 /myblog/entries/add//auth/groups/add/ 这样的URL 。然而,对于用户对象的添加页面( /auth/user/add/ )是个特殊情况,因为它不会显示所有的表单域,它显示两个密码域等等。 我们 可以 在视图中特别指出以解决这种情况:

雪雪 10-20 13:24

O(∩_∩)O哈哈~笑死

对这一段的评论会显示在这里
def add_stage(request, app_label, model_name):
    if app_label == 'auth' and model_name == 'user':
        # do special-case code
    else:
        # do normal code
silent 11-03 05:47

app_label和model_label两个参数是如何获得的?URL中既没有URLConf参数,也没有以字典的形式传送额外参数啊。

roger 11-22 17:40

回楼上,这里是采用按位置传参数,那两个参数的名称不要紧,只要位置对了就行了,他对应url模式中的两个变量,也就是auth和usr位置的那两个

zzm88 08-08 08:56

原来如此谢谢ls

虎头蔓 01-19 06:09

url里面用括号括出来的两个字符串就是views里面的两个变量啦~! 不加括号会报错~!

徐云东 11-29 02:55

这个是正则表达式的无名分组!。。

对这一段的评论会显示在这里

不过,就如我们多次在这章提到的,这样做并不优雅: 因为它把URL逻辑放在了视图中。 更优雅的解决方法是,我们要利用URLconf从顶向下的解析顺序这个特点:

对这一段的评论会显示在这里
urlpatterns = patterns('',
    # ...
    ('^auth/user/add/$', views.user_add_stage),
    ('^([^/]+)/([^/]+)/add/$', views.add_stage),
    # ...
)
对这一段的评论会显示在这里

在这种情况下,象 /auth/user/add/ 的请求将会被 user_add_stage 视图处理。 尽管URL也匹配第二种模式,它会先匹配上面的模式。 (这是短路逻辑。)

千里山南 01-05 03:59

短路逻辑,即合理又十分有用

yoncan 08-15 14:24

1. 匹配即退出 2.不在乎哪个精确匹配

haobo 12-02 03:25

建议把文档中本应是像的象转换过来。

jowhok 12-30 07:10

特意查了下楼上说的像和象的区别,貌似很有渊源,这里不用纠结

对这一段的评论会显示在这里

从URL中捕获文本

对这一段的评论会显示在这里

每个被捕获的参数将被作为纯Python字符串来发送,而不管正则表达式中的格式。 举个例子,在这行URLConf中:

对这一段的评论会显示在这里
(r'^articles/(?P<year>\d{4})/$', views.year_archive),
对这一段的评论会显示在这里

尽管 \d{4} 将只匹配整数的字符串,但是参数 year 是作为字符串传至 views.year_archive() 的,而不是整型。

对这一段的评论会显示在这里

当你在写视图代码时记住这点很重要,许多Python内建的方法对于接受的对象的类型很讲究。 许多内置Python函数是挑剔的(这是理所当然的)只接受特定类型的对象。 一个典型的的错误就是用字符串值而不是整数值来创建 datetime.date 对象:

Dunboa 11-23 03:25

"一个典型的的错误就是用字符串值而不是整数值来创建 datetime.date 对象"是不是讲反了呢?如果改成“ 一个典型的的错误就是用整数值而不是字符串值来创建 datetime.date 对象:”这样呢?看例子应该是这样。。。。

Dunboa 11-23 03:27

。。。。上面我想我可能理解错误了,作者这样写估计是从反面角度去说的,汗

djangoliu 04-19 09:09

作者写的好像没问题。这里应该是用整型而不是字符串。所以作者说用字符串而不是整型是个“典型的错误”

Black Glory 06-24 10:08

原文正确,date方法的参数必须是整型,不能是字符串

Brad 03-22 03:22

典型错误:狗捉老鼠

Brad 03-22 03:23

就这逻辑还学计算机。。。。

对这一段的评论会显示在这里
>>> 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)
对这一段的评论会显示在这里

回到URLconf和视图处,错误看起来很可能是这样:

对这一段的评论会显示在这里
# urls.py

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

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)
匿名读者 10-26 09:51

没有为传递的变量进行命名?

roger 11-22 17:44

按位置传参

对这一段的评论会显示在这里

因此, day_archive() 应该这样写才是正确的:

对这一段的评论会显示在这里
def day_archive(request, year, month, day):
    date = datetime.date(int(year), int(month), int(day))
Rex.Ye 01-12 04:56

明白

对这一段的评论会显示在这里

注意,当你传递了一个并不完全包含数字的字符串时, int() 会抛出 ValueError 的异常,不过我们已经避免了这个错误,因为在URLconf的正则表达式中已经确保只有包含数字的字符串才会传到这个视图函数中。

路人 11-29 08:44

前文曾经强调不能依赖url map所返回的值,因为该页面可能被不同的url所调用而不能保证正确,所以验证类型还是必须的

AlsoTang 12-13 17:53

同楼上。。。书前后的观念出现了一点小的冲突。。

nono 12-20 09:14

你如果输入的不是数字,是不会进入这个view处理的,因此这里不用判断的

andmz 04-16 08:14

正则已经能确保抽取的不可能是其他的字符串

小白 08-03 10:22

3、4楼,楼主不是那个意思,楼主的意思是说这个view可能被其他url调用,而其他url传递进来的参数就不一定经过正则过滤了。作者全面章节说到过类似问题,因此才说有点前后矛盾了。

noooop 04-19 15:58

前面才讲不要相信服务器传过来的东西。。。

arnold 07-05 06:57

最好做一下校验,服务器校验是一个稳定系统所必须的

匿名读者 08-14 07:37

正则已经能确保抽取的不可能是其他的字符串

agon 10-24 12:41

前后不一,是因为前面那几章里将plus时间的例子,hours_ahead这个view的例子,尽管url正则做了过滤,不保证其他url也用这个view,而那个url可能没有过滤,所以最好还是做一个try比较妥当

迷途小前端 12-10 06:43

好纠结——

needle 10-19 03:47

哈,真矫情,像我,这里的逻辑合理,没有其他的url映射到此视图时,没有问题。但有LS说的隐患,要么做处理,要么加注释!个人偏向在任何隐患处加注释。

wangyue 10-12 05:45

>>> 加不加验证不是关键,关键是你能找出错误并且处理掉,这才是程序员的能力体现

对这一段的评论会显示在这里

决定URLconf搜索的东西

对这一段的评论会显示在这里

当一个请求进来时,Django试着将请求的URL作为一个普通Python字符串进行URLconf模式匹配(而不是作为一个Unicode字符串)。 这并不包括 GETPOST 参数或域名。 它也不包括第一个斜杠,因为每个URL必定有一个斜杠。

krator 08-25 16:25

原文是每个url必有一个开头的斜杠。或者说必以斜杠开始

andmz 04-16 08:17

第一个'/'和第一个'?'之间的东西来做匹配

对这一段的评论会显示在这里

例如,在向 http://www.example.com/myapp/ 的请求中,Django将试着去匹配 myapp/ 。在向 http://www.example.com/myapp/?page=3 的请求中,Django同样会去匹配 myapp/

对这一段的评论会显示在这里

在解析URLconf时,请求方法(例如, POSTGETHEAD )并 不会 被考虑。 换而言之,对于相同的URL的所有请求方法将被导向到相同的函数中。 因此根据请求方法来处理分支是视图函数的责任。

对这一段的评论会显示在这里

视图函数的高级概念

对这一段的评论会显示在这里

说到关于请求方法的分支,让我们来看一下可以用什么好的方法来实现它。 考虑这个 URLconf/view 设计:

对这一段的评论会显示在这里
# urls.py

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

urlpatterns = patterns('',
    # ...
    (r'^somepage/$', views.some_page),
    # ...
)

# views.py

from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response

def some_page(request):
    if request.method == 'POST':
        do_something_for_post()
        return HttpResponseRedirect('/someurl/')
    elif request.method == 'GET':
        do_something_for_get()
        return render_to_response('page.html')
    else:
        raise Http404()
对这一段的评论会显示在这里

在这个示例中,some_page() 视图函数对POSTGET 这两种请求方法的处理完全不同。 它们唯一的共同点是共享一个URL地址: /somepage/.正如大家所看到的,在同一个视图函数中对POSTGET 进行处理是一种很初级也很粗糙的做法。 一个比较好的设计习惯应该是,用两个分开的视图函数——一个处理POST 请求,另一个处理GET 请求,然后在相应的地方分别进行调用。

桔了个仔 02-22 13:34

"/somepage/." 改为"/somepage/".

BeginMan 04-28 01:35

为什么说在同一个视图函数中对`` POST`` 和`` GET`` 进行处理是一种很初级也很粗糙的做法?

haobo 12-03 07:12

大概是因为在some_page()里有调用了另一个函数比较浪费时空吧

wangyue 10-12 05:56

>>> 回复2L >>> 一个函数应该尽量设计体现为对应一种功能,这样更易用,更易读。

对这一段的评论会显示在这里

我们可以像这样做:先写一个视图函数然后由它来具体分派其它的视图,在之前或之后可以执行一些我们自定的程序逻辑。 下边的示例展示了这个技术是如何帮我们改进前边那个简单的some_page() 视图的:

对这一段的评论会显示在这里
# views.py

from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response

def method_splitter(request, GET=None, POST=None):
    if request.method == 'GET' and GET is not None:
        return GET(request)
    elif request.method == 'POST' and POST is not None:
        return POST(request)
    raise Http404

def some_page_get(request):
    assert request.method == 'GET'
    do_something_for_get()
    return render_to_response('page.html')

def some_page_post(request):
    assert request.method == 'POST'
    do_something_for_post()
    return HttpResponseRedirect('/someurl/')

# urls.py

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

urlpatterns = patterns('',
    # ...
    (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}),
    # ...
)
lazy 03-13 12:36

谁能解释一下这里为什么要有 assert request.method == 'GET' ,没有的话会有什么影响

melzg 03-24 08:34

Assert是保证method正确,否则的话,就会抛出异常,不会继续往下执行。可以在你的代码里简单加一个这样类似的判断,看一下效果。

melzg 03-24 08:39

当assert正确时,继续执行。否则抛出异常。我在一个View函数中这样声明:assert 1 > 2 执行后,显示 AssertionError at /search/ No exception supplied Request Method: GET Request URL: http://127.0.0.1:8000/search/ Django Version: 1.3.1 Exception Type: AssertionError

xiaocainiaok 04-16 12:27

传进来的数据GET不是转为字符串了?怎么又返回

weetao 05-10 19:20

@xiaocainiaok 传进来的是函数

googcheng 06-13 07:26

return GET(request) 这里的get 与 url 里面的GET 一样吗

Rex.Ye 01-12 05:10

直接把函数名当参数传递? 习惯了.Net,再看这弱类型语言还真奇怪啊。

noooop 04-19 16:02

这不是弱类型,是所有对象都是第一类对象。。

老张 06-08 04:21

感觉这么做并没有带来什么好处,反而更麻烦了啊

lincy 08-18 11:46

@Rex.Ye ,弱类型。。。太无知了,你这样下去迟早是落泪型

ERic 10-09 14:31

这个是1.4版本的,后面的更高级版本提供了decorators,感兴趣的童鞋请看 https://docs.djangoproject.com/en/1.5/topics/http/decorators/

soulgeek 12-28 06:14

感觉python里面好多用到decorators的

jeremy 03-23 06:44

不是弱类型 是高阶函数

seakia 04-29 08:28

刚开始我看的时候猛地也迷糊一个,GET=None这里的GET和method那里的GET不是一回事,GET=None这里传入的是函数,感觉改一下参数名字好一些,比如GetFunction = None,下边那里写成{'GetFunction':views.some_page_get,'PostFunction':views.some_page_post}这样子是不是清除一些~~~

MO 10-04 11:07

赞楼上!!秒懂!

kknd li 12-31 14:13

这里传入参数不应该用GET和POST,容易和GET参数和POST参数搞混。要是用get_method和post_method说不定好些

YANG WANG 09-07 04:07

建议吧method_splitter()中的参数GET,POST改成get_method和post_method 容易混淆 这只是为了在url字典中进行传参 参数为函数 名

admin 10-18 08:09

GET is not None?有这样写法吗?不是应该 if request.GET: 吗

Ramos 04-19 09:25

这模块,和装饰器没啥区别

xiaopanddxiong 08-10 07:46

@seakia 赞一个,秒懂,就是将函数作为参数传递,但是这里命名让初学者产生疑惑了

wangyue 10-12 06:10

>>> 最好一个路由也用来体现一个动作(就和一个函数对应一种功能一样),而不是既能GET又能POST,一个路由被设计成执行多个动作,逻辑是复杂的,工作量也大了。

wangyue 10-12 06:13

>>> Python的鼻祖是Lisp,在函数式语言中函数也是一等公民,可以作为参数去传递的,可以作为返回值被返回(也就是装饰器的作用)。

对这一段的评论会显示在这里

让我们从头看一下代码是如何工作的:

阿杰 02-22 09:03

下面这段乱的不像样了

sai 07-14 13:22

这个。。urlpattersn 里面固定的传GET、POST对应函数名称也不会比在函数里面直接函数里面写好吧,其实都是写死了代码。 if request.method == 'GET' and GET is not None: return some_page_get(request)

hekun 08-01 07:01

设计模式告诉我们,要尽量少用if,但是这里和前面的if request.method == 'GET' and GET is not None: return some_page_get(request)都用了if,所以这里和前面应该在本质上都一样,都不优雅。

qing 01-23 06:59

谁能告诉我这样有啥意义啊,在url.py里面何必还要传参数? return some_page_get(request)不就行了么

jowhok 12-30 07:25

@楼上 这样可以在urlconf里重新指定视图而不需要取更改视图代码,我想应该是这个理念

admin 10-18 08:33

我觉得使用url传递参数,费脑子,找来找去的更麻烦,也没见怎么优雅。python格言不是明言胜于晦涩吗?最讨厌跳来跳去的程序,看起来好像牛逼,实际上为了牛逼而牛逼,哪天自己找都费劲。

匿名读者 01-25 07:44

这是用什么软件自动翻译的,好乱!

andrew 07-12 07:35

这里估计遵循python的哲学,“用一种方法,最好是只有一种方法来做一件事!”

对这一段的评论会显示在这里

我们写了一个新的视图,method_splitter() ,它根据request.method 返回的值来调用相应的视图。可以看到它带有两个关键参数,GETPOST ,也许应该是 视图函数 。如果request.method 返回GET ,那它就会自动调用GET 视图。 如果request.method 返回的是POST ,那它调用的就是POST 视图。 如果request.method 返回的是其它值(如:HEAD ),或者是没有把GETPOST 提交给此函数,那它就会抛出一个Http404 错误。

对这一段的评论会显示在这里

在URLconf中,我们把/somepage/ 指到method_splitter() 函数,并把视图函数额外需要用到的GETPOST 参数传递给它。

对这一段的评论会显示在这里

最终,我们把some_page() 视图分解到两个视图函数中some_page_get()some_page_post() 。这比把所有逻辑都挤到一个单一视图的做法要优雅得多。

haobo 12-03 07:55

谁能给我解释一下,这些改变怎么就优雅的多了?明明用了更多的变量和调用啊。

needle 10-19 04:18

逻辑分离得更清晰,如果业务代码很多,很难看。比如调试的时候,你会看到一个大if下有一大砣业务处理,再一个elif又有一大堆。你要不停的用滚轮。而把函数名写到urlconf参数中,你将很容易定位到该视图。你也可以不用urlconf参数,直接在method_splitter中调some_page_get和some_page_post,不过从思维清晰度上来讲还不够直接,因为调试时要多跳转了一次。想想有多少javaer是喜欢写大if的~

对这一段的评论会显示在这里

注意,在技术上这些视图函数就不用再去检查request.method 了,因为method_splitter() 已经替它们做了。 (比如,some_page_post() 被调用的时候,我们可以确信request.method 返回的值是post 。)当然,这样做不止更安全也能更好的将代码文档化,这里我们做了一个假定,就是request.method 能象我们所期望的那样工作。

imairy 08-01 10:42

这里有点不明白了,some_page_post()这个函数什么时候会被调用?request.method==‘POST’的时候? 为什么会在这个时候被调用?

imairy 08-01 10:53

好吧,看的不够仔细,上面代码没注意urls.py中的修改,结合着看就明白了

匿名读者 08-14 08:07

在url.py中 (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}), # ... 只是将POST或GET字典值作为参数传给视图views.method_splitter,然后views.method_splitter判断后。。。通过request(POST或GET字典值)去请求对应的视图模块??

匿名读者 08-14 08:08

在url.py中 (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}), # ... 只是将POST或GET字典值作为参数传给视图views.method_splitter,然后views.method_splitter判断后。。。通过request(POST或GET字典值)去请求对应的视图模块??里边封装着由`` request.method`` 的返回值来分派不同的视图的程序。这个是重点

杜浩 05-26 05:48

在method_spliter函数中第一个返回值 return GET(request) 对应的是 return views.some_page_get(request) 这里GET的值是由urls那边传过来的 二个返回的也是同理 这里的GET不同于 request.method== 'GET'里的GET

对这一段的评论会显示在这里

现在我们就拥有了一个不错的,可以通用的视图函数了,里边封装着由request.method 的返回值来分派不同的视图的程序。关于method_splitter() 就不说什么了,当然,我们可以把它们重用到其它项目中。

对这一段的评论会显示在这里

然而,当我们做到这一步时,我们仍然可以改进method_splitter 。从代码我们可以看到,它假设GetPOST 视图除了request 之外不需要任何其他的参数。那么,假如我们想要使用method_splitter 与那种会从URL里捕捉字符,或者会接收一些可选参数的视图一起工作时该怎么办呢?

zhongqi 02-15 07:21

那种会从URL里捕捉字符?这里到底是要解决什么实际问题?

melzg 03-24 08:44

要解决的是:向下一级方法(post或get处理)传递方法时,不让其他需要的参数丢掉。

imairy 08-01 10:47

又蒙了。。。楼上说的也不太懂,这里能有个实例解释一下就好了

coco 09-08 08:32

这里的GET 和POST 是参数,代表了两个函数,也就是some_page_get和some_page_post这两个函数。在上面的例子中,这两个函数的参数只有request。return GET(request)其实就是return some_page_get(request),调用了下面的函数。这时没有向some_page_get传递参数,如果需要传递参数的话,解决方法,敬请期待

wangyue 10-12 06:24

>>> 这里对于初学者不是很友好,作者可能偏爱函数式编程吧,如果各位读过 SICP(初学者可以读一下第一章) ,对高阶函数式编程应该一点都不陌生,这里作者就是想体现高阶函数式编程的特点,抽象,抽象,再抽象,有时候过度抽象了也不好,反而变成了过度设计的现象,也就是为了抽象而抽象。

对这一段的评论会显示在这里

为了实现这个,我们可以使用Python中一个优雅的特性 带星号的可变参数 我们先展示这些例子,接着再进行解释

对这一段的评论会显示在这里
def method_splitter(request, *args, **kwargs):
    get_view = kwargs.pop('GET', None)
    post_view = kwargs.pop('POST', None)
    if request.method == 'GET' and get_view is not None:
        return get_view(request, *args, **kwargs)
    elif request.method == 'POST' and post_view is not None:
        return post_view(request, *args, **kwargs)
    raise Http404
呜呜祖拉 07-14 08:49

这段代码不太理解,谁能帮忙解释解释啊?谢谢了

zhou 03-17 10:25

回楼上的pop的时候有返还值的,相当于赋值

ode2free 05-08 08:34

kwargs.pop('GET', None) 是不是和 kwargs.get('GET',None) 一样?

Black Glory 06-24 10:18

D.pop(k[,d]) -> v, remove specified key and return the corresponding value.If key is not found, d is returned if given, otherwise KeyError is raised. 与get类似,pop会删除指定键,并返回该键所对应的值

zdxhave 04-26 13:44

pop(key[, default]) If key is in the dictionary, remove it and return its value, else return default. If default is not given and key is not in the dictionary, a KeyError is raised.使用pop()方法确保下次调用时的正确性,使用完后就删除当时的key-value键值对

yhben 02-01 05:09

Python tips: 什么是*args和**kwargs?[ http://www.cnblogs.com/fengmk2/archive/2008/04/21/1163766.html ]

athos 03-15 15:23

注意要结合上一段代码的url部分来看:urlpatterns = patterns('', # ... (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}), # ... ),刚才想了好久才明白为什么带进来的kwargs会有以 GET 和 POST为key的字典。

noooop 04-19 16:05

亮的不敢直视,写这个的一定超神了

zxw 07-25 14:08

@athos 正解

paulzhao 08-17 02:25

确实要结合上面的例子一起看,下面说了**两个星号会转成字典,(r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}这个URL会把GET和POST封装在一个字典kwargs里,使用字典的pop来删除key会返回value给变量,那么变量get_view和post_view就会存GET和POST里的value(即views.some_page_get和views.some_page_post),在对request.method判断来返回对应的function(返回方法对象并传递参数)

Joe 02-27 08:59

元组形参的arg有什么用在这里?如果没有传参进来,那字典就会被作为arg传递进来而不是kwargs。求指教!

Joe 02-27 09:01

sorry。想错了。这种方式确实很灵活!

jstech 07-01 08:08

java servlet 框架,处理 service 方法。再根据请求方法,具体调用,get,post

wangyue 10-12 06:29

>>> 这里不明白的可以先看看廖雪峰老师的python教程,函数的参数这一章,弄明白以后(当然也要理解函数式编程的特点,函数可以用做函数的参数传递和返回)理解起来会很简单。

huhu 06-28 03:33

**kwargs只是为了提取对应函数,而且通过pop的方式,已经将kwargs清空了,为啥后面return的函数里的参数还要带**kwargs?就算没清空,要**kwargs何用?

对这一段的评论会显示在这里

这里,我们重构method_splitter(),去掉了GET和POST两个关键字参数,改而支持使用args和和kwargs(注意号) 这是一个Python特性,允许函数接受动态的、可变数量的、参数名只在运行时可知的参数。 如果你在函数定义时,只在参数前面加一个号,所有传递给函数的参数将会保存为一个元组. 如果你在函数定义时,在参数前面加两个号,所有传递给函数的关键字参数,将会保存为一个字典

xmandbq 02-17 05:17

*args和和**kwargs(注意*号)--这里多了一个“和”字

对这一段的评论会显示在这里

例如,对于这个函数

cjyfff 03-08 14:04

囧,原来下面就有解析,我还到处去找**kwargs的用法

对这一段的评论会显示在这里
def foo(*args, **kwargs):
    print "Positional arguments are:"
    print args
    print "Keyword arguments are:"
    print kwargs
对这一段的评论会显示在这里

看一下它是怎么工作的

对这一段的评论会显示在这里
>>> foo(1, 2, 3)
Positional arguments are:
(1, 2, 3)
Keyword arguments are:
{}
>>> foo(1, 2, name='Adrian', framework='Django')
Positional arguments are:
(1, 2)
Keyword arguments are:
{'framework': 'Django', 'name': 'Adrian'}
对这一段的评论会显示在这里

回过头来看,你能发现我们用method_splitter()*args接受**kwargs函数参数并把它们传递到正确的视图。any 但是在我们这样做之前,我们要调用两次获得参数kwargs.pop()``GET``POST,如果它们合法的话。 (我们通过指定pop的缺省值为None,来避免由于一个或者多个关键字缺失带来的KeyError)

xmandbq 02-17 05:16

any?

ode2free 05-08 08:52

回过头来看method_splitter() ,你能发现我们用*args和**kwargs接受任何函数参数并把它们传递到正确的视图。

Black Glory 06-24 10:21

为什么用pop不用get?

vincent 08-02 03:19

之所以用pop不用get,我觉得是因为要把GET参数跟POP参数给用字典中移除,防止在 get_view(request, *args, **kwargs)时 它作为参数传入对应的调用函数中。

melzg 03-24 08:53

同意vicent。因为POST,GET是在URL层指定的,不需要继续传下去。否则,不小心用了,反而有问题。

roger 11-22 18:08

这里的url的额外参数貌似只能是字典吧,那这个*args还有意义么

7 01-30 09:22

可能还会用到没有命名的捕获的参数,它们是位置参数,不字典

7 01-30 09:23

可能还会用到没有命名的捕获的参数,它们是位置参数,不是字典

zzm88 08-09 10:08

回头看methodsplitter(),我们用*args和*kwargs 接收 所有参数,再传递至合适的view(视图)。但,在做这件事之前,我们用kargs.pop()方法以获得GET 与POST 参数(如果有的话)。PS:默认值None是避免KeyError 错误

bobo1732 05-14 09:15

看了楼上三们评注,那是豁然开朗呀!!

heliar 07-21 10:04

传递下去会产生什么错误呢

heliar 07-21 10:05

想了一下,如果传递下去是不是会导致自身调用自身最后产生死循环

kkllyfx 08-02 04:52

kkllyfx 08-02 04:52

看不太懂

mihello 08-19 07:10

来补看评论,话说过去两天网站挂了

horizonshd 09-16 02:00

使用pop而不是get:是因为在 get_view = kwargs.pop('GET', None)后在调用return get_view(request, *args, **kwargs)时,**kwargs已经不需要传递视图函数是什么,因为已经找到了( get_view)

wangyue 10-12 06:33

>>> 使用pop或者get方法都一样,http请求中的数据被抽象到了request对象中,视图函数在处理请求时只关心请求内容(request对象)是什么。

对这一段的评论会显示在这里

包装视图函数

对这一段的评论会显示在这里

我们最终的视图技巧利用了一个高级python技术。 假设你发现自己在各个不同视图里重复了大量代码,就像 这个例子:

对这一段的评论会显示在这里
def my_view1(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/accounts/login/')
    # ...
    return render_to_response('template1.html')

def my_view2(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/accounts/login/')
    # ...
    return render_to_response('template2.html')

def my_view3(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/accounts/login/')
    # ...
    return render_to_response('template3.html')
对这一段的评论会显示在这里

这里,每一个视图开始都检查request.user是否是已经认证的,是的话,当前用户已经成功登陆站点否则就重定向/accounts/login/ (注意,虽然我们还没有讲到request.user,但是14章将要讲到它.就如你所想像的,request.user描述当前用户是登陆的还是匿名)

Youbuwei 11-24 07:10

是的话,当前用户已经成功登陆站点;否则就重定向/accounts/login/

Youbuwei 11-24 07:11

就如你所想像的 - request.user描述当前用户是登陆的还是匿名

yang 07-01 11:01

所以说,以后的django和python版本加入了@decrator,装饰器!

sai 04-24 01:46

登陆 -> 登录

wangyue 10-12 06:44

>>> 使用装饰器还是很方便的,当然你有兴趣的话可以自己写一个类似装饰器的高阶函数(造轮子大误)

对这一段的评论会显示在这里

如果我们能够丛每个视图里移除那些 重复代,并且只在需要认证的时候指明它们,那就完美了。 我们能够通过使用一个视图包装达到目的。 花点时间来看看这个:

leo 12-11 15:20

如果我们能够"丛"每个视图里移除那些 重复代 --> 如果我们能够"从"每个视图里移除那些 重复代

Youbuwei 11-24 05:59

重复代码

cjyfff 03-08 14:37

无“码”了

对这一段的评论会显示在这里
def requires_login(view):
    def new_view(request, *args, **kwargs):
        if not request.user.is_authenticated():
            return HttpResponseRedirect('/accounts/login/')
        return view(request, *args, **kwargs)
    return new_view
RK 05-22 10:58

相当于javascript里的call,apply之类的用法

can. 11-14 02:31

其实python还提供了一种@修饰符的写法,更简洁一些

sarow 12-19 10:45

可以做 java 中的 filter

Rex.Ye 01-12 05:36

直接把函数当参数传递,相当于.Net中的委托吧。

Rex.Ye 01-12 05:39

这一段为什么要定义一个new_view?直接这样不行吗? def requires_login(view): def new_view(request, *args, **kwargs): if not request.user.is_authenticated(): return HttpResponseRedirect('/accounts/login/') return view(request, *args, **kwargs) return new_view

Rex.Ye 01-12 05:39

这一段为什么要定义一个new_view?直接这样不行吗? def requires_login(view): if not request.user.is_authenticated(): return HttpResponseRedirect('/accounts/login/') return view(request, *args, **kwargs)

匿名读者 03-27 07:44

这里是一个闭包啊

匿名读者 08-14 08:37

逻辑太乱了,require_login(view1)->return new_view->执行new_view()函数-》判断结果

匿名读者 08-14 08:42

逻辑太乱了,require_login(view1)->return new_view->执行new_view()函数-》判断结果;另外再问一下传递的参数view1视图,到底传递了什么,view1的视图名称,还是POST或GET内容?

zzZ 03-11 08:53

每次碰到这样的写法都要想半天才明白,怎么破

dani 03-21 03:06

http://blackgu.blogbus.com/logs/171867049.html 我觉得这个讲解看完了有助于理解这段代码

John 07-06 06:55

一切皆对象,就好理解了,犀利

mihello 08-19 07:23

之所以还有一层new_view是要返回一个 函数对象,就是func 而不是func(),好好回忆urlpattern是这样写的:url(r'^something/$', func,{...}), 这里就是要一个func。如果没有了new_view 按照楼上所说,那么返回的是 view(request, **args, **kwargs) 是func()了,不符合.... so, 要多一层,这是在下的拙见。。。。

迷途小前端 12-10 08:28

同意ls拙见

latyas 01-02 06:42

没有@decorator这种漂亮的语法支持?

www 02-24 02:42

这段建议看原版,更容易理解,reference: This function, requires_login, takes a view function (view) and returns a new view function (new_view). The new function, new_view is defined within requires_login and handles the logic of checking request.user.is_authenticated() and delegating to the original view (view).

杜浩 05-26 06:10

这个比较像python里的装饰器 decorator

大隐 08-22 15:37

这里看懂了,一直纠结为啥要*args 和**kwargs 因为你不知道view会穿过来什么参数,所以用两个可变的参数,一个是接受元组,一个接受字典。然后进行处理

wangyue 10-12 06:47

>>> 其实很多初学者大可不必纠结这些,看不懂就是看不懂,暂时记住怎么用就好了,不必大费周折去弄懂过于难理解的东西,见识广了以后自然会明白很多以前弄不懂的东西。

猪头哥哥 02-02 07:19

这里的函数可以用login_required代替 具体使用方法请百度一下

huhu 06-28 03:47

大函数里面定义了一个小函数,并返回这个小函数。小函数就是用来判断要不要执行大函数传进来的view

对这一段的评论会显示在这里

函数requires_login,传入一个视图函数view,然后返回一个新的视图函数new_view.这个新的视图函数new_view在函数requires_login内定义 处理request.user.is_authenticated()这个验证,从而决定是否执行原来的view函数

coco 09-08 08:49

在requires_login的函数中,定义了一个新的视图,这个视图对是否是用户登录进行判断,如果登录失败,就重新定向到'/accounts/login/',否则就进入视图view这个视图的界面。new_view相当于一个变化的视图,由requires_login函数传入的参数view(这是一个视图)的属性决定的。

冯日 11-11 07:16

有点想绕口令

YANG WANG 09-12 01:14

require_login 中参数为view函数名, 进入函数后进行选择判断。view(*args, **kwargs)这样是因为传入的view函数时名不知道里面的参数 精妙

对这一段的评论会显示在这里

现在,我们可以从views中去掉if not request.user.is_authenticated()验证.我们可以在URLconf中很容易的用requires_login来包装实现.

对这一段的评论会显示在这里
from django.conf.urls.defaults import *
from mysite.views import requires_login, my_view1, my_view2, my_view3

urlpatterns = patterns('',
    (r'^view1/$', requires_login(my_view1)),
    (r'^view2/$', requires_login(my_view2)),
    (r'^view3/$', requires_login(my_view3)),
)
zy_sunshine 07-04 05:10

@ 是一个pre处理

vincent 08-02 04:01

是不是还要在每个view函数的前面,加上@requires_login 装饰器啊?

melzg 03-24 08:58

不错的解决方式。

phonty 04-10 11:03

@vincent,不用。

zivee 07-02 08:11

这里使用装饰器是否更加合理一些呢?

sevear 02-16 10:02

虽然这里可以使用装饰器,但是还是觉得这个思路不错。

YG 06-28 07:53

有这样一个问题,如果某个试图将来不需要处理登录了,我是在URLConf中把requireLogin的装饰函数去掉,这个行为的变更应该是View去处理呢,还是Controller去处理呢?层次有没有混乱?

匿名读者 08-14 08:35

这段没看懂

匿名读者 08-14 08:41

逻辑太乱了,require_login(view1)->return new_view->执行new_view()函数-》判断结果;另外再问一下传递的参数view1视图,到底传递了什么,view1的视图名称,还是POST或GET内容?

lincy 08-18 12:11

在Python中,一切皆对象

coco 09-08 08:54

如果url中这么写的话,那么,在new_view中的后两个参数*args,**kwargs的值在哪里???求解!

Lwxiang 11-04 04:45

这里其实是这样的: 例如第一个url 把my_view1这个视图函数作为参数传递到requires_login里面。在requires_login中 如果该用户已经验证->调用view函数[也就是传递进来的my_view1(该函数会返回一个httpresponse)]->作为答复返回给new_view->再返回给requires_login->作为视图函数

fly2fire 02-27 08:27

漂亮

Joe 02-27 09:24

工厂/闭合函数

Yanis 05-13 12:22

这一段实在是太强大了。

Heliar 07-21 10:53

我的理解是,例如第一个url,require_login(myview_1)其实就是一个命名空间内有myview_1的new_view函数,传给他的参数就是request,同时处理后可以返回myview_1函数

冯日 11-11 07:18

yang 07-01 11:05

个人觉得,这就是装饰器的实现原理吧!!!如果使用@语法,那么在视图函数前指明@就可以了?不知道是不是这样。作者这里这样演示我想只是为了突出装饰器的原理。

mr.liu 08-12 08:57

以my_view1为例,个人理解如下:当访问http://ip/view1时, requires_login(my_view1)将试图函数 my_view1 作为参数传递,然后返回函数 new_view ,接着执行 new_view 中的认证过程,如果认证通过,就返回 view 执行后的结果(这里传递的是 my_view1),最后将结果展现给用户。 大家有疑惑,还是亲自写试试吧,方便加深。

徐云东 11-29 03:24

我觉得如果是传参数的话,应该在url里面传递的吧,然后把参数中的view函数对象pop出来,再传递给view函数。

YANG WANG 09-12 01:51

也可以写成这样 def require_login(request, view): if not request.user.is_authenticated(): return HttpResponseRedirect('/account/login') else: return view(request) 然后url字典配置里面 url(r'^view1/$',require_login, {'view':my_view1}) 这样功能是不是差不多呢?

大隐 08-22 15:39

我日,纠结了半天,为什么把my_view1传入进行,这样只是替换掉了,判断是否登录的代码块,牛逼 这样只需要调用这一个函数就好了,就可以验证了,

wangyue 10-12 06:53

>>> 看来楼上很多还是在纠结,非常推荐初学者去读读sicp,读完第一章就好了,顺便每节习题尽量做一下,不会做网上有答案,读完第一章就能理解抽象的奥秘,python的装饰器本质就是一个高阶函数,很多人只知道装饰器怎么用,但不了解装饰器是怎么实现的,本质还是对高阶函数编程的特性不理解。 >>> 文中的例子就是在告诉你怎么造一个装饰器的轮子。

对这一段的评论会显示在这里

优化后的代码和前面的功能一样,但是减少了代码冗余 现在我们建立了一个漂亮,通用的函数requires_login()来帮助我们修饰所有需要它来验证的视图

对这一段的评论会显示在这里

包含其他URLconf

心扬 02-22 08:15

这个有点用,可以把URL写到不同的文件里

hahaman 05-04 06:54

请问这些外部的urls.py文件放哪儿?我怎么总是导入失败呢?

lxd 10-15 05:16

在工程文件夹中urls.py中: (r'^',include('app1.urls')), 在应用文件夹中urls.py中:(r'^aaa/$', view1), 在浏览器URL栏中输入http://127.0.0.1:8000/aaa/,即可访问view1视图

lxd 10-15 05:23

或者:在工程文件夹中urls.py中: (r'^app1/',include('app1.urls')), 在应用文件夹中urls.py中:(r'^aaa/$', view1), 在浏览器URL栏中输入http://127.0.0.1:8000/app1/aaa/,即可访问view1视图。app1是应用名。此种方式合理一点

Kazuhira 07-13 08:05

用在多个基于Django的站点上 , 意思是用在多个project上。django→project→app

blackysy 07-09 06:20

@楼上,这里用在多个app上比较合适些,一般一个project会有多个app,每个app下面又有自身的url.py, 那么project里的url.py可以包本工程下所有的app里的url.py。

对这一段的评论会显示在这里

如果你试图让你的代码用在多个基于Django的站点上,你应该考虑将你的URLconf以包含的方式来处理。

对这一段的评论会显示在这里

在任何时候,你的URLconf都可以包含其他URLconf模块。 对于根目录是基于一系列URL的站点来说,这是必要的。 例如下面的,URLconf包含了其他URLConf:

对这一段的评论会显示在这里
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^weblog/', include('mysite.blog.urls')),
    (r'^photos/', include('mysite.photos.urls')),
    (r'^about/$', 'mysite.views.about'),
)
yang 07-01 11:06

记得加‘’

tang 11-06 03:07

在前面看到django2.2已经弃用django.conf.urls,那要怎么使用这个包含功能

对这一段的评论会显示在这里

在前面第6章介绍Django的admin模块时我们曾经见过include. admin模块有他自己的URLconf,你仅仅只需要在你自己的代码中加入include就可以了.

对这一段的评论会显示在这里

这里有个很重要的地方: 例子中的指向 include() 的正则表达式并 包含一个 $ (字符串结尾匹配符),但是包含了一个斜杆。 每当Django遇到 include() 时,它将截断匹配的URL,并把剩余的字符串发往包含的URLconf作进一步处理。

匿名读者 08-14 08:47

每当Django遇到 include() 时,它将截断匹配的URL,并把剩余的字符串发往包含的URLconf作进一步处理。?

coco 09-08 08:59

@ls include中有他自己的url和他的重新匹配方式

cjyfff 03-08 15:04

因为包含了$就代表匹配结束了

1 01-12 03:38

$ :表示一个匹配的结尾。 此处包含,将仅仅匹配weblog/结尾的url,无法匹配weblog/?xx=xxx 从而无法传参。

sinoyster 07-02 07:32

mark

徐云东 11-29 03:31

比如admin中有这样的URL路由。 `url(r'^login/$', self.login, name='login')` 而mysite中的的URL有这样的路由: `url(r'^admin/', include(admin.site.urls))` 存在这样一个地址 admin/login/ mysite获取的地址是`admin/login/`,它匹配了`admin/`,然后将`admin/`部分截断,传递`login/`给admin模块,admin模块获取到的URL是`login/`,它就直接匹配上self.login函数了。

wangyue 10-12 07:01

>>> 个人理解include函数相当于Flask中的蓝图,在app内注册蓝图,添加前缀。这个前缀的功能和django中include函数之前用来匹配的字符串。 >>> 另外说一句,web编程最好先学习下网络编程基础,Flask相对django更简单上手,有一定的flask编程经验再学习django会容易很多

对这一段的评论会显示在这里

继续看这个例子,这里就是被包含的URLconf mysite.blog.urls

对这一段的评论会显示在这里
from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^(\d\d\d\d)/$', 'mysite.blog.views.year_detail'),
    (r'^(\d\d\d\d)/(\d\d)/$', 'mysite.blog.views.month_detail'),
)
969333315@qq.com 03-26 09:02

from django.conf.urls import patterns, include, url (1.6.2)

YANG WANG 09-13 03:56

很不错的一个功能

对这一段的评论会显示在这里

通过这两个URLconf,下面是一些处理请求的例子:

对这一段的评论会显示在这里
  • /weblog/2007/ :在第一个URLconf中,模式 r'^weblog/' 被匹配。 因为它是一个 include() ,Django将截掉所有匹配的文本,在这里是 'weblog/' 。URL剩余的部分是 2007/ , 将在 mysite.blog.urls 这个URLconf的第一行中被匹配到。 URL仍存在的部分为 2007/ ,与第一行的 mysite.blog.urlsURL设置相匹配。
  • /weblog//2007/(包含两个斜杠) 在第一个URLconf中,r’^weblog/’匹配 因为它有一个include(),django去掉了匹配的部,在这个例子中匹配的部分是’weblog/’ 剩下的部分是/2007/ (最前面有一个斜杠),不匹配mysite.blog.urls中的任何一行.
  • /about/ : 这个匹配第一个URLconf中的 mysite.views.about 视图。
zhongqi 02-15 10:13

这里举两个//的例子是要说明什么?理想情况下,应该保证两个斜杠与一个斜杠的效果相同才对啊

roger 11-23 05:20

为了表示截断只包括weblog/

匿名读者 08-14 08:48

牛逼!!

zxb 08-27 07:22

2l 说的对

对这一段的评论会显示在这里

捕获的参数如何和include()协同工作

对这一段的评论会显示在这里

一个被包含的URLconf接收任何来自parent URLconfs的被捕获的参数,比如:

对这一段的评论会显示在这里
# root urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
)

# foo/urls/blog.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^$', 'foo.views.blog_index'),
    (r'^archive/$', 'foo.views.blog_archive'),
)
zqz 09-13 01:39

按上面操作 会报一个 “No module named foo.urls.blog”,如何解决

KJS 02-03 09:52

hello django

小白 08-03 13:06

不是截断了吗??难道捕获的变量就不截断吗

roger 11-23 05:22

截断和参数传递是两回事

helpme 05-24 13:42

mark, 截断和捕获参数还需研究,求懂的大神给科普

yoncan 08-15 15:47

/yoncan/blog/archive/

对这一段的评论会显示在这里

在这个例子中,被捕获的 username 变量将传递给被包含的 URLconf,进而传递给那个URLconf中的 每一个 视图函数。

lgy 11-14 11:08

这个功能很牛逼,mark

yang 07-01 11:15

出现这种情况很少吧?作为新手的理解是我觉得尽量不要在父url模式中指定命名组?

对这一段的评论会显示在这里

注意,这个被捕获的参数 总是 传递到被包含的URLconf中的 每一 行,不管那些行对应的视图是否需要这些参数。 因此,这个技术只有在你确实需要那个被传递的参数的时候才显得有用。

ruandao 04-24 10:06

如果视图不需要参数会怎样?

ruandao 04-24 10:16

试了下,如果不需要参数 。。 则 出错...

ode2free 05-08 23:22

即使视图不需要也要接受这个参数?

melzg 03-24 09:23

果然是出错。

melzg 03-24 09:28

果然是出错。这样的话,必须是传过去的参数,在对应urlpatterns中视图函数都同样需要,才可以。

给以上几位 01-29 07:51

可以在参数如下定义 def func(request,*args,**kwargs): 如此不会KeyError, 上一章讲了.

对这一段的评论会显示在这里

额外的URLconf如何和include()协同工作

ode2free 05-08 23:24

额外的URLconf选项 如何和include()协同工作

对这一段的评论会显示在这里

相似的,你可以传递额外的URLconf选项到 include() , 就像你可以通过字典传递额外的URLconf选项到普通的视图。 当你这样做的时候,被包含URLconf的 每一 行都会收到那些额外的参数。

对这一段的评论会显示在这里

比如,下面的两个URLconf在功能上是相等的。

吕少磊 03-30 08:23

比如,下面的两个URLconf在功能上是一样的。

对这一段的评论会显示在这里

第一个:

对这一段的评论会显示在这里
# urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^blog/', include('inner'), {'blogid': 3}),
)

# inner.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^archive/$', 'mysite.views.archive'),
    (r'^about/$', 'mysite.views.about'),
    (r'^rss/$', 'mysite.views.rss'),
)
对这一段的评论会显示在这里

第二个

对这一段的评论会显示在这里
# urls.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^blog/', include('inner')),
)

# inner.py

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
    (r'^about/$', 'mysite.views.about', {'blogid': 3}),
    (r'^rss/$', 'mysite.views.rss', {'blogid': 3}),
)
对这一段的评论会显示在这里

这个例子和前面关于被捕获的参数一样(在上一节就解释过这一点),额外的选项将 总是 被传递到被包含的URLconf中的 每一 行,不管那一行对应的视图是否确实作为有效参数接收这些选项,因此,这个技术只有在你确实需要那个被传递的额外参数的时候才显得有用。 因为这个原因,这种技术仅当你确信在涉及到的接受到额外你给出的选项的每个URLconf时有用的才奏效。

游泳的猪 10-07 12:09

这段翻译的好难懂

匿名读者 02-03 09:51

hello django

roger 11-23 05:26

意思就是你include里的urlpattern对应的每一行view函数都必须需要那个额外的参数才行,如果不是每一个都需要,那就不要用这个

frank 08-19 15:05

这段翻译的根本看不懂。。

atlas 10-03 09:07

这一章没有一个真正的实例运行起来跑,看着感觉好吃力,根本没有搞懂多少

xiaopanddxiong 08-10 09:24

头都大了 难懂啊

wangyue 10-12 08:27

>>> 我转意一下,如果你准备在一个url字符串匹配中同时使用命名组参数和include函数,那么所有能匹配到该字符串相关的视图函数都被动的接收了命名组定义的参数,所以你需要在所有的视图函数中额外处理这些参数,比如用 def func(request, **kwargs): ... 的形式处理它

tangdou 11-06 03:41

这样,如果调用不需要参数的站点时会报错

对这一段的评论会显示在这里

下一章

对这一段的评论会显示在这里

这一章提供了很多高级视图和URLconfs的小提示和技巧。 接下来,在Chapter 9,我们将会将这个先进的处理方案带给djangos模板系统。

haiyang 04-13 07:28

djangos -> django

Adoo 01-23 03:05

这一章看得我好晕

mr.liu 08-12 09:21

同上。

sai 04-24 03:14

djangos -> django的

对这一段的评论会显示在这里

GNU Free Document License. Hosting公司殷勤提供

对这一段的评论会显示在这里