有些视图反映基本的网络开发中的一个常见情况:根据 URL 中的参数从数据库中获取数据、载入模板文件然后返回渲染后的模板。 由于这种情况特别常见,通用视图将通用模式抽象到你甚至不需要编写Python代码来编写应用程序的程度。例如,ListView和DetailView泛型视图分别抽象了"显示对象列表"和"显示特定类型对象的详细页面"的概念。
📌当编写一个 Django 应用时,应该先评估一下通用视图是否可以解决你的问题,你应该在一开始使用它,而不是进行到一半时重构代码。
以投票应用为例,关于投票应用的更多内容,请查看
首先重构polls/urls.py
python
from django.urls import path
from . import views
app_name = "polls"
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。这是必要的,因为我们将使用DetailView通用视图来取代detail()和results()视图,并且它期望从URL捕获的主键值称为"pk"。
我们将删除旧的 index, detail, 和 results 视图,并用 Django 的通用视图代替。
重构 polls/views.py 文件
python
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]
class DetailView(generic.DetailView):
model = Question
template_name = "polls/detail.html"
class ResultsView(generic.DetailView):
model = Question
template_name = "polls/results.html"
def vote(request, question_id):
... # same as above, no changes needed.
📌每个通用视图都需要知道它将作用于哪个模型。这可以使用model属性或通过定义get_queryset()方法(如IndexView中所示)来提供。
📌默认情况下,通用视图 DetailView 使用一个叫做 <app name>/<model name>_detail.html 的模板。在投票的例子中,它将使用 "polls/question_detail.html" 模板。template_name 属性是用来告诉 Django 使用一个指定的模板名字,而不是自动生成的默认名字。
📌ListView 使用一个叫做 <app name>/<model name>_list.html 的默认模板;使用 template_name 来告诉 ListView 使用我创建的已经存在的 "polls/index.html" 模板。
📌对于 DetailView , question 变量会自动提供------ 因为我们使用 Django 的模型(Question), Django 能够为 context 变量决定一个合适的名字。然而对于 ListView, 自动生成的 context 变量是 question_list。为了覆盖这个行为,使用 context_object_name 属性,表示我们想使用 latest_question_list。
启动服务器,使用一下基于通用视图的新投票应用。