(6)http://hi.baidu.com/derris/blog/item/e8ee10fafd711915a9d31185.html
(8)http://hi.baidu.com/derris/blog/item/f490f213dc314f095baf53cc.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),
)
有一种相对简洁的写法,这样起码不用再写2边:
from mysite import views
urlpatterns = patterns('',
(r'^hello/$', views.hello),
(r'^time/$', views.current_datetime),
(r'^time/plus/(d{1,2})/$', views.hours_ahead),
)
甚至不用模块导入直接写,但是必须要声明为字符串,。
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'),
)
还可以更好的处理一下,在第一个参数中声明好导入模块。
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
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'),
)
可以声明调试模式,提供一些参数信息:
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),
)
django自动根据正则表达式匹配对应的函数调用,对于函数参数,有2种传递方式:
按顺序的匿名参数传递和指定参数名字的传递方式,如:
urlpatterns = patterns('',
(r'^articles/(\d{4})/$', views.year_archive),
(r'^articles/(\d{4})/(\d{2})/$', views.month_archive),
) 产生函数调用:month_archive(request, '2006', '03')
urlpatterns = patterns('',
(r'^articles/(?P\d{4})/$', views.year_archive),
(r'^articles/(?P\d{4})/(?P\d{2})/$', views.month_archive),
) 产生函数调用:month_archive(request, year='2006', month='03')
注意在同一个模式中是不能2者混用的。
urlpattern甚至能够传递一个字典参数:
urlpatterns = patterns('',
(r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}),
(r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),
)
这样对应的处理。注意参数名字和字典的主键必须一致起来就可以,参数类型可以任意。最好加上参数的默认值,就会灵活很多。
def foobar_view(request, template_name=‘default’):
m_list = MyModel.objects.filter(is_new=True)
return render_to_response(template_name, {'m_list': m_list})
注意:参数的数值优先于patter匹配的数值,就是说,比如
在(r'^mydata/(?P\d+)/$', views.my_view, {'id': 3})看来,
对于/mydata/2/ 或者 /mydata/432432/) id这个变量都会为3。
模式匹配是有优先原则的,就是django会按照第一个能匹配的进行处理。
这样我们就可以写一个几乎能适应所有情况的一个固定模式的view处理函数:
# 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})
这样只要编辑好对应的model就可以了~!然后需要改动的只有urls.py文件和对应的模型,在views中的处理都是一样的。
由于request的请求一般分为post和get的,而且会有跟着参数,我们写一个比较通用的处理函数:# views.py
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render_to_response
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
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}),
# ...
)
参数*args和和**kwargs(注意*号) 这是一个Python特性,允许函数接受动态的、可变数量的、参数名只在运行时可知的参数。 如果你在函数定义时,只在参数前面加一个*号,所有传递给函数的参数将会保存为一个元组. 如果你在函数定义时,在参数前面加两个*号,所有传递给函数的关键字参数,将会保存为一个字典
最后处理一个重复代码的例子:假设每个函数都要验证用户,我们这样处理一下就好了:
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
函数requires_login,传入一个视图函数view,然后返回一个新的视图函数new_view.这个新的视图函数new_view在函数requires_login内定义 处理request.user.is_authenticated()这个验证,从而决定是否执行原来的view函数 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)),
)
关于url的包含可以写的更具有模块性一点,比如前面我们学的amdin模块的添加。如:
urlpatterns = patterns('',
(r'^weblog/', include('mysite.blog.urls')),
(r'^photos/', include('mysite.photos.urls')),
(r'^about/$', 'mysite.views.about'),
)
他会根据指定目录下面对应方法进行处理。如(r'^admin/', include(admin.site.urls)),碰到admin,django会截断后面的内容,发送给admin.site.urls方法中对应的pattern进行处理。
最后注意的是inlcude包含在父urls捕获的变量或者声明的变量,会自动传递给所有的下级视图处理函数。不处理也可以~~