当前位置:K88软件开发文章中心网站服务器框架django → 文章内容

Django 高级视图和URL配置

减小字体 增大字体 作者:佚名  来源:网上搜集  发布时间:2019-1-25 14:19:18

nder_to_response('page.html')def some_page_post(request): assert request.method == 'POST' do_something_for_post() return HttpResponseRedirect('/someurl/')# urls.pyfrom django.conf.urls.defaults import *from mysite import viewsurlpatterns = patterns('', # ... (r'^somepage/$', views.method_splitter, {'GET': views.some_page_get, 'POST': views.some_page_post}), # ...)让我们从头看一下代码是如何工作的:我们写了一个新的视图,method_splitter() ,它根据request.method 返回的值来调用相应的视图。可以看到它带有两个关键参数,GET 和POST ,也许应该是 视图函数 。如果request.method 返回GET ,那它就会自动调用GET 视图。 如果request.method 返回的是POST ,那它调用的就是POST 视图。 如果request.method 返回的是其它值(如:HEAD ),或者是没有把GET 或POST 提交给此函数,那它就会抛出一个Http404 错误。在URLconf中,我们把/somepage/ 指到method_splitter() 函数,并把视图函数额外需要用到的GET 和POST 参数传递给它。最终,我们把some_page() 视图分解到两个视图函数中some_page_get() 和some_page_post() 。这比把所有逻辑都挤到一个单一视图的做法要优雅得多。注意,在技术上这些视图函数就不用再去检查request.method 了,因为method_splitter() 已经替它们做了。 (比如,some_page_post() 被调用的时候,我们可以确信request.method 返回的值是post 。)当然,这样做不止更安全也能更好的将代码文档化,这里我们做了一个假定,就是request.method 能象我们所期望的那样工作。现在我们就拥有了一个不错的,可以通用的视图函数了,里边封装着由request.method 的返回值来分派不同的视图的程序。关于method_splitter() 就不说什么了,当然,我们可以把它们重用到其它项目中。然而,当我们做到这一步时,我们仍然可以改进method_splitter 。从代码我们可以看到,它假设Get 和POST 视图除了request 之外不需要任何其他的参数。那么,假如我们想要使用method_splitter 与那种会从URL里捕捉字符,或者会接收一些可选参数的视图一起工作时该怎么办呢?为了实现这个,我们可以使用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这里,我们重构method_splitter(),去掉了GET和POST两个关键字参数,改而支持使用*args和和*kwargs(注意号) 这是一个Python特性,允许函数接受动态的、可变数量的、参数名只在运行时可知的参数。 如果你在函数定义时,只在参数前面加一个号,所有传递给函数的参数将会保存为一个元组. 如果你在函数定义时,在参数前面加两个号,所有传递给函数的关键字参数,将会保存为一个字典例如,对于这个函数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()GETPOST,如果它们合法的话。 (我们通过指定pop的缺省值为None,来避免由于一个或者多个关键字缺失带来的KeyError)包装视图函数我们最终的视图技巧利用了一个高级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描述当前用户是登陆的还是匿名)如果我们能够丛每个视图里移除那些 重复代,并且只在需要认证的时候指明它们,那就完美了。 我们能够通过使用一个视图包装达到目的。 花点时间来看看这个: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函数现在,我们可以从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_view3urlpatterns = patterns('', (r'^view1/$', requires_login(my_view1)), (r'^view2/$', requires_login(my_view2)), (r'^view3/$', requires_login(my_view3)),)优化后

上一页  [1] [2] [3] [4] [5] [6]  下一页


Django 高级视图和URL配置