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