最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 详解Django中的urls和视图views

    正文概述    2020-02-19   202

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

    详解Django中的urls和视图views

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

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

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

    我们写了一个新的视图,`` 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)


    起源地下载网 » 详解Django中的urls和视图views

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元