4.2 use generic views

master
Jason Zhu 2020-10-20 20:36:07 +11:00
parent e0267685cc
commit c7cb960daa
3 changed files with 110 additions and 15 deletions

View File

@ -325,4 +325,95 @@ def results(request, question_id):
</ul>
<a href="{% url 'polls:detail' question.id %}">Vote again?</a>
```
```
### 4.2 使用通用视图(generic views):代码还是少点好
Web 开发中的一个常见情况:根据 URL 中的参数从数据库中获取数据、载入模板文件然后返回渲染后的模板。 由于这种情况特别常见Django 提供一种快捷方式,叫做“通用视图”系统。
让我们将我们的投票应用转换成使用通用视图系统,这样我们可以删除许多我们的代码。我们仅仅需要做以下几步来完成转换,我们将:
* 转换 URLconf。
* 删除一些旧的、不再需要的视图。
* 基于 Django 的通用视图引入新的视图。
#### Modify URLconf of polls
Change
```python
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
```
to
```python
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'),
```
* 注意,第二个和第三个匹配准则中,路径字符串中匹配模式的名称已经由 <question_id> 改为 <pk> (primary key)。
#### Modify Views
Target: Replace `index`, `details` & `results` views using Django's generic views that named in `polls/urls.py`
```python
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
```
改为
```python
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'
```
两个通用视图: ListView 和 DetailView 。这两个视图分别抽象“显示一个对象列表”和“显示一个特定类型对象的详细信息页面”这两种概念。
* 每个通用视图需要知道它将作用于哪个模型。 这由 model 属性 (i.e. model members) 提供。
* DetailView 期望从 URL 中捕获名为 "pk" 的主键值,所以我们为通用视图把 question_id 改成 pk 。
解释 DetailView
* 默认情况下,通用视图 DetailView 使用一个叫做 <app name>/<model name>_detail.html 的模板。
* e.g. "polls/question_detail.html" template for us.
* 但是我们可以用 model member `template_name` 来指定模板
解释 ListView
* ListView 也使用一个叫做 <app name>/<model name>_list.html 的默认模板
* 而这里我们使用 `template_name` 来指定模板
* 我们提供 context_object_name 属性,表示我们想使用 latest_question_list
重启服务器后就是新的投票应用同样的html但是内部用了generic view

View File

@ -5,11 +5,11 @@ from . import views
app_name = 'polls'
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
path('', views.IndexView.as_view(), name='index'),
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]

View File

@ -2,22 +2,26 @@ from django.http import request, HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.template import loader
from django.urls import reverse
from django.views import generic
from .models import Question, Choice
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
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 results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try: