想在我们有两个视图:
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
的返回值来分派不同的视图的程序.