django--高级视图

1.请求方法(POST/GET)的分支:

# 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()

在同一个函数中处理POST和GET是很初级很粗糙的,一个比较好的习惯应该是用两个分开的视图函数--一个处理POST请求,一个处理GET请求


# 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}),
    # ...
)

  • We’ve written a new view, method_splitter(), that delegates to otherviews based onrequest.method. It looks for two keyword arguments,GET andPOST, which should be view functions. Ifrequest.method is'GET', then it calls theGET view. Ifrequest.method is'POST', then it calls thePOST view. Ifrequest.method is something else (HEAD, etc.), or ifGET orPOST were not supplied to the function, then it raises anHttp404.

  • In the URLconf, we point /somepage/ atmethod_splitter() and passit extra arguments – the view functions to use forGET and POST,respectively.

  • Finally, we’ve split the some_page() view into two view functions –some_page_get() andsome_page_post(). This is much nicer thanshoving all of that logic into a single view.

    Note that these view functions technically no longer have to checkrequest.method, becausemethod_splitter() does that. (By the timesome_page_post() is called, for example, we can be confidentrequest.method is 'post'.) Still, just to be safe, and also toserve as documentation, we stuck in anassert that makes surerequest.method is what we expect it to be.

2.创建一个通用视图:

抽取出我们代码中共性的东西是一个很好的编程习惯。 比如,像以下的两个Python函数:

def say_hello(person_name):
    print 'Hello, %s' % person_name

def say_goodbye(person_name):
    print 'Goodbye, %s' % person_name
我们可以把问候语提取出来变成一个参数:
def greet(person_name, greeting):
    print '%s, %s' % (greeting, person_name)

同样的思想也可以用到django视图中去

比如:

# urls.py

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^events/$', views.event_list),
    (r'^blog/entries/$', views.entry_list),
)

# views.py

from django.shortcuts import render_to_response
from mysite.models import Event, BlogEntry

def event_list(request):
    obj_list = Event.objects.all()
    return render_to_response('mysite/event_list.html', {'event_list': obj_list})

def entry_list(request):
    obj_list = BlogEntry.objects.all()
    return render_to_response('mysite/blogentry_list.html', {'entry_list': obj_list})

这两个视图做的事情,实质上都一样,显示一系列的对象(obj_list)。让我们把它们显示的对象类型抽象出来:

# 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()#lower()是变小写,即:Event变event,BlogEntry变blogentry,因为template名字是小写
    return render_to_response(template_name, {'object_list': obj_list})

注意,这里的model.Event和model.BlogEntry在model.py文件里面

★我们通过model函数在URLconf中直接传递了模型类,URLconf参数的字典可以传递任何类型的对象的,而不仅经是string

★这一行,model.object.all(),我们不需要知道这里的model到底是什么类型,只要他有一个objects的属性和all()的方法,我们就能够使用他了。

★我们使用 model.__name__.lower() 来决定模板的名字。 每个Python的类都有一个__name__ 属性返回类名。 这特性在当我们直到运行时刻才知道对象类型的这种情况下很有用。 比如,BlogEntry 类的 __name__ 就是字符串 'BlogEntry'

★这里的object_list就是传递给模版的通用的变量名,你可以自己定义


这段不太好理解,多看看,明白参数分别是什么含义就容易了


3.了解硬编码的值和捕捉值之间的优先级(答案是硬编码优先)

当冲突出现时,额外的URLconf参数优先于捕获值,例如:

from django.conf.urls.defaults import *
from mysite import views

urlpatterns = patterns('',
    (r'^mydata/(?P\d+)/$', views.my_view, {'id': 3}),
)

命名组变量名字,一个额外的URLconf参数包含的变量名字相同,{'id' : 3}会被使用

(比如,/mydata/2/ 或者 /mydata/3434/ 都会做id设置为3即:/mydata/3/ 来对待, 不管URL里面捕捉到什么值)

你可能感兴趣的:(django)