URLconf技巧
1、URL匹配中使用命名组
我们在urls.py中使用正则匹配url的时候,所调用视图中的函数这个过程,其实就是调用函数传递参数的过程,是否使用命名组就类似与调用函数时是否使用关键字参数
例:
一般是这样写:
urlpatterns = [
#ex: /polls/extends/
url(r‘extends/$‘, views.extends_test, name=‘extends_test‘),
#ex: /polls/search_form/
url(r‘search_form/$‘, views.search_form, name=‘search_form‘),
]
等同于这样的函数调用:
extends_test(request,’extends’)
如果利用命名组,可以改成这样(注意!调用的extends_test函数必须有设置接受yyy的参数)
urlpatterns = [
#ex: /polls/extends/
url(r‘(?P<yyy>extends)/$‘, views.extends_test,name=‘extends_test‘),
#ex: /polls/search_form/
url(r‘search_form/$‘, views.search_form, name=‘search_form‘),
]
等同于这样的函数调用:
extends_test(request,yyy=’extends’)
2、向视图传递额外的参数
平时我们是这样使用url匹配,根据匹配到的传入的url来判断,执行相应的操作
#urls.py
urlpatterns = [
url(r‘extends/$‘,views.extends_test),
url(r‘search_form/$‘, views.extends_test),
]
#views.py
def extends_test(request,url)
ifurl == ‘extends’:
xxx
elseif url == ‘search_form’:
xxxx
return render_to_response(‘polls/extends.html’)
如果想得到更多的额外参数呢?应该这样操作,原来匹配的url还是会起作用,额外传多了一个template_name的值。这种使用额外的URLconf参数的技术以最小的代价给你提供了向视图函数传递额外信息的一个好方法,要掌握。
urlpatterns = [
url(r‘extends/$‘,views.extends_test,{‘template_name’:’template1.html’}),
url(r‘search_form/$‘, views.extends_test, {‘template_name’:’template2.html’}),
]
#views.py
def extends_test(request,template_name)
iftemplate_name == ‘template1.html’:
xxx
elseif template_name == ‘template2.html’:
xxxx
return render_to_response(template_name)
3、伪造一些需要的参数
例如,你可能有一个显示某一个特定日子的某些数据的应用,URL类似这样的:
/mydata/jan/01/
/mydata/jan/02/
/mydata/jan/03/
# ...
/mydata/dec/30/
/mydata/dec/31/
这太简单了,你可以在一个URLconf中捕捉这些值,像这样(使用命名组的方法):
urlpatterns = [
url(r‘mydata/(?P<month>\w{3})/(?P<day>\d{2})/$‘,views.my_view),
]
然后视图函数的原型看起来会是:
def my_view(request, month, day):
# ....
这种解决方案很直接,没有用到什么你没见过的技术。 当你想添加另外一个使用 my_view 视图但不包含month和/或者day的URL时,问题就出现了。
比如你可能会想增加这样一个URL, /mydata/birthday/ , 这个URL等价于 /mydata/jan/06/ 。这时你可以这
样利用额外URLconf参数:
urlpatterns = [
url(r‘mydata/birthday/$‘,views.my_view,{‘month’:’jan’,’day’:’06’}),
url(r‘mydata/(?P<month>\w{3})/(?P<day>\d{2})/$‘,views.my_view),
]
这里最帅的地方莫过于你根本不用改变你的视图函数。视图函数只会关心它是否获得了month和day参数,它不会去管这些参数到底是捕捉回来的还是被额外提供的。
4、匹配到的参数和额外参数直接的优先级
当冲突出现的时候,额外URLconf参数优先于捕捉值。也就是说,如果URLconf捕捉到的一个命名组变量和一
个额外URLconf参数包含的变量同名时,额外URLconf参数的值会被使用。
5、视图设置默认参数
例:
def page(request,num=’1’)
6、url匹配的顺序
urls.py中url的匹配顺序是从上而下的,只要匹配了就不会再匹配剩余的
7、请谨记url中匹配到的传递到函数的值的类型都是字符串!
每个被捕获的参数将被作为纯Python字符串来发送,而不管正则表达式中的格式。举个例子,在这行
URLConf中:
(r‘^articles/(?P<year>\d{4})/$‘,views.year_archive),
尽管 \d{4} 将只匹配整数的字符串,但是参数 year 是作为字符串传至views.year_archive() 的,而不是整型。
def day_archive(request, year, month, day):
date= datetime.date(int(year), int(month), int(day))
8、URLconf匹配url的具体方式
当一个请求进来时,Django试着将请求的URL作为一个普通Python字符串进行URLconf模式匹配(而不是作
为一个Unicode字符串)。这并不包括 GET 或 POST 参数或域名。 它也不包括第一个斜杠,因为每个URL必定有一个斜杠。
例:
在向http://www.example.com/myapp/ 的请求中,Django将试着去匹配 myapp/ 。
在向http://www.example.com/myapp/?page=3的请求中,Django同样会去匹配 myapp/ 。
在解析URLconf时,请求方法(例如, POST , GET , HEAD )并 不会 被考虑。
换而言之,对于相同的URL的所有请求方法将被导向到相同的函数中。因此根据请求方法来处理分支是视图函数的责任
9、视图函数的可变参数
如果urls.py中调用的视图函数的参数不确定,就可以用这种方法来处理。一个*表示收集为元组,两个*表示收集为字典。要注意的带*参数的放置顺序和使用时传递参数的位置,详细内容看书上的函数一章。
例:
def foo(*args, **kwargs):
print"Positional arguments are:"
printargs
print"Keyword arguments are:"
printkwargs
工作方式
>>> 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)
或
def method_splitter(request, *args,**kwargs):
get_view= kwargs.pop(‘GET‘, None)
post_view= kwargs.pop(‘POST‘, None)
ifrequest.method == ‘GET‘ and get_view is not None:
return get_view(request, *args, **kwargs)
elifrequest.method == ‘POST‘ and post_view is not None:
return post_view(request, *args, **kwargs)
raiseHttp404
10、包含其他URLconf
l URLconf都可以包含其他URLconf模块,使用include()。 对于根目录是基于一系列URL的站点来说,这是必要的。
例:
urlpatterns = [
url(r‘^polls/‘,include(‘polls.urls‘)),
]
当url是http://192.168.61.172:8000/polls/extends/时,第一条url规则将会忽略http://192.168.61.172:8000/这一部分,匹配polls/,但不会把polls/送到include里的polls.urls,只会把剩余的extends/送过去,匹配polls.urls里的规则
l 包含其他URLconf的同时,还可以传递额外的参数过去
例:
urlpatterns = [
url(r‘^polls/‘,include(‘polls.urls‘),{‘user_name’:’dx’}),
]