Some advanced concepts about the URL view function in Django

Source: Internet
Author: User
Speaking about the branch of the request method, let's take a look at some good ways to implement it. Consider this Urlconf/view design:

# urls.pyfrom django.conf.urls.defaults Import *from mysite Import viewsurlpatterns = Patterns (',  # ...  (R ' ^somepage/$ ', views.some_page),  # ...) # views.pyfrom django.http import Http404, httpresponseredirectfrom django.shortcuts import render_to_responsedef 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 ()

In this example, the ' some_page () ' View function is completely different from the processing of the two request methods of ' POST ' and ' GET '. The only thing they have in common is to share a URL address: '/somepage/. ' As you can see, it is a very primitive and coarse practice to handle ' POST ' and ' GET ' in the same view function. A good design habit should be to use two separate view functions-one to process ' POST ' requests, another to process ' GET ' requests, and then to make calls separately in the appropriate place.

We can do it like this: Write a view function and then assign other views, before or after we can execute some of our custom program logic. The following example shows how this technique can help us improve the simple "some_page ()" View of the front:

# views.pyfrom django.http import Http404, httpresponseredirectfrom django.shortcuts import render_to_responsedef 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 are not None:    return POST (Request)  raise Http404def some_page_get (req uest):  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.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}),  # ...)

Let's start with a look at how the code works:

We wrote a new view, ' Method_splitter () ', which invokes the corresponding view based on the value returned by ' Request.method '. You can see that it comes with two key parameters, ' GET ' and ' POST ', and maybe it should be * view function *. If ' request.method ' returns ' get ', it will automatically invoke the ' Get ' view. If ' Request.method ' returns ' Post ', then it calls the ' post ' view. If ' Request.method ' returns a different value (such as ' HEAD '), or if ' get ' or ' POST ' is not submitted to this function, then it throws a ' Http404 ' error.

In Urlconf, we refer to '/somepage/' to the ' method_splitter () ' function and pass it the ' GET ' and ' POST ' parameters that the view function needs to use extra.

Finally, we decompose the ' some_page () ' view into two view functions ' Some_page_get () ' and ' some_page_post () '. This is much more elegant than squeezing all the logic into a single view.

Note that technically these view functions do not have to check for ' Request.method ', because ' method_splitter () ' has done it for them. (for example, when "Some_page_post ()" is called, we can be sure that the value returned by ' Request.method ' is ' post '. Of course, it's safer and better to document the code, and here's the assumption that ' request.method ' can work as we expect.

Now we have a nice, generic view function that encapsulates a program that assigns a different view by the return value of ' Request.method '. There is nothing to say about ' method_splitter () ', of course, we can reuse them in other projects.

However, when we do this, we can still improve the ' method_splitter '. From the code we can see that it assumes that "Get" and "POST" views do not require any other parameters other than ' request '. So what if we want to use ' method_splitter ' to work with a view that captures characters from a URL or receives some optional arguments?

To achieve this, we can use a graceful feature in Python variable parameters with asterisks we'll show these examples first, and then we'll explain them.

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 are not None:    return Get_view (Request, *args, **kwargs)  el if Request.method = = ' POST ' and Post_view are not None:    return Post_view (Request, *args, **kwargs)  raise Http404

Here, we refactor method_splitter (), remove the Get and post two keyword parameters, and support the use of *args and and **kwargs (Note *) This is a Python feature that allows the function to accept dynamic, variable quantities, Parameter names are only known at run time. If you are in a function definition and only precede the argument with an * number, all arguments passed to the function will be saved as a tuple. If you add two * in front of the parameter in the function definition, all the keyword arguments passed to the function will be saved as a dictionary

For example, for this function

def foo (*args, **kwargs):  print "positional arguments is:"  print args  print "Keyword arguments is:"  Print Kwargs

Take a look at how it works.

>>> foo (1, 2, 3) positional arguments is: (1, 2, 3) Keyword arguments are:{}>>> foo (1, 2, name= ' Adrian ', F Ramework= ' Django ') positional arguments is: (1, 2) Keyword arguments are:{' framework ': ' Django ', ' name ': ' Adrian '}

Looking back, you can see that we use Method_splitter () and *args to accept the **kwargs function parameters and pass them to the correct view. Any but before we do this, we're going to call two times to get the parameter Kwargs.pop () Getpost, if they're legit. (We avoid the keyerror of one or more keyword deletions by specifying the default value of Pop to none)

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.