Use generic views: Less code is better.
这些视图代表了基本Web开发的常见情况:根据URL中传递的参数从数据库中获取数据,加载模板并且返回呈现的模板。因为这很常见,Django提供了一个快捷方式,称为“Generic Views”系统。
通用视图抽象了常见的模式,甚至不需要编写Python代码就可以编写应用程序。
让我们将投票应用程序转换为使用通用视图系统,这样我们就可以删除自己的一些代码。我们只需要采取几个步骤来进行转换。我们将
- 转换URLconf (Convert the URLconf)
- 删除(修改)一些旧的、不需要的视图。(Delete some of the old, unneeded views.)
- 基于Django的泛型视图引入新的视图。(Introduce new views based on Django's generic views.)
转换URLconf
urlpatterns = [ path('', views.IndexView.as_view(), name='index'), path('<int:pk>/', views.DetailView.as_view(), name='detail'), path('<int:pk>/results/', views.ResultsView.as_view(), name='results'), path('<int:question_id>/vote/', views.vote, name='vote'), ]
请注意,第二个和第三个模式的路径字符串中匹配模式的名称已从<question_id>更改为<pk>。
删除旧的views(并且引入 generic views)
# polls/views.py from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.views import generic from .models import Choice, Question class IndexView(generic.ListView): template_name = 'polls/index.html' context_object_name = 'latest_question_list' def get_queryset(self): """Return the last five published questions.""" return Question.objects.order_by('-pub_date')[:5]
# def detail(request, question_id): # question = get_object_or_404(Question, pk=question_id) # return render(request, 'polls/detail.html', {'question': question})
class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html'
- 每个通用视图都需要知道它将作用于什么模型(models)。这是使用model属性提供的。例如,model = Question
- DetailView 通用视图期望从URL捕获的主键值被称为“pk”,因此我们将通用视图的question_id更改为pk。例如,detail()函数中之前的参数是question_id。
默认情况下,DetailView 通用视图使用被称为 <app_name>/<model_name>_detail.html 的模板。例如,template_name = 'polls/detail.html'。template_name属性通常会告诉Django要使用一个确切的模板名字,而不是自动装配默认的模板名字。
类似地,ListView通用视图使用名为<app name> / <model name> _list.html的默认模板; 我们使用template_name属性告诉ListView使用我们现有的“polls / index.html”模板。
在手册的前几页中,模板提供了一个上下文,其中包含 question 和 latest_question_list 类似的上下文变量。对 DetailView来说,如果我们使用一个Django模型-Question,那么question变量是自动提供的,不用自己声明。并且,对ListView来说,也会自动装配上下文变量-question_list。为了覆盖这个属性,我们提供了 context_object_name 属性,指定我们想要使用 latest_question_list。作为一种可代替的方法,你可以改变你的模板来匹配新的默认上下文变量。但是,让Django使用您想要的变量要容易得多。(就是说,不用自定义,默认就好)