想在我们有两个视图:

def thinkingview(request):
    user = request.user
    if request.method == 'GET':
        return render(request, 'think.html', {'user': user})
    elif request.method == 'POST:
        user = request.user
        data_form = ThinkingForm(request.POST)
        if data_form.is_valid():
            data_form.save()
            return redirect('index')
        else:
            return render(request, 'think.html', {'user': user, 'error': data_form.errors})

 

def questionview(request):
    user = request.user
    if request.method == 'GET':
        user = request.user
        return render(request, 'question.html', {'user': user})
    elif request.method == 'POST:
        data_form = QuestionForm(request.POST)
        if data_form.is_valid():
            data_form.save()
            return redirect('index')
        else:
            return render(request, 'question.html', {'user': user, 'error': data_form.errors})

 

这两个视图非常相似,GET渲染页面并预置用户信息,POST提交文本数据,不同的只有tamplate和form这两个对象。现在把这两个对象抽象出来,创建一个通用的视图:

# view.py
def reportview(request, tamplate_name, form):
    user = request.user
    if request.method == 'GET':
        user = request.user
        return render(request, tamplate_name, {'user': user})
    elif request.method == 'POST:
        data_form = form(request.POST)
        if data_form.is_valid():
            data_form.save()
            return redirect('index')
        else:
            return render(request, tamplate_name, {'user': user, 'error': data_form.errors})

 

通过URLconf的传递额外参数的方式来传递这两个对象:

# urls.py
from django.conf.urls import url
from myapp import forms, views

urlpatterns = [
    url(r'^thinking/$', views.report, {'tamplate_name': 'thinking.html', 'form': forms.ThinkingForm}),
    url(r'^question/$', view.report, {'tamplata_name': 'question.html', 'form': forms.QuestionForm})

 

这样就有了一个可复用的、与对象无关的视图(在URLconf中甚至可以传递model)!如果再有类似功能的视图时就可以重用这个report视图,而不需要再写视图代码。

现在来做一些优化,在同一个视图函数中对POST 和GET 进行处理是一种比较粗糙的做法,一个比较好的设计习惯应该是,用两个分开的视图函数——一个处理POST请求,另一个处理GET请求,然后在相应的地方分别进行调用。
写一个分发函数,由它来分派GET和POST请求:

#views.py
from django.views.decorators.http import require_http_methods
...


def method_splitter(request, *args, **kwargs):
    #对http method进行分发
    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

@require_http_methods('GET')
def report_get(request, tamplate_name):
    user = request.user
    return render(request, tamplate_name, {'user': user})

@require_http_methods('POST')
def report_post(request, tamplate_name, form):
    data_form = form(request.POST)
    if data_form.is_valid():
        data_form.save()
        return redirect('index')
    else:
        return render(request, tamplate_name,  'user': request.user, 'error': data_form.errors})


#urls.py
urlpatterns = [
    url(r'^thinking/$', views.report, {'tamplate_name': 'thinking.html', 'form': forms.ThinkingForm, 'get': view.report_get, 'post': view.report_post}),
    url(r'^question/$', view.report, {'tamplata_name': 'question.html', 'form': forms.QuestionForm, 'get': view.report_get, 'post': view.report_post})

 

现在我们就拥有了一个不错的,可以通用的视图函数了,里边封装着由request.method 的返回值来分派不同的视图的程序.

posted on 2017-08-16 10:39  雷子-LL  阅读(1017)  评论(0编辑  收藏  举报