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

@ -326,3 +326,94 @@ def results(request, question_id):
<a href="{% url 'polls:detail' question.id %}">Vote again?</a> <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' app_name = 'polls'
urlpatterns = [ urlpatterns = [
# ex: /polls/ # ex: /polls/
path('', views.index, name='index'), path('', views.IndexView.as_view(), name='index'),
# ex: /polls/5/ # ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'), path('<int:pk>/', views.DetailView.as_view(), name='detail'),
# ex: /polls/5/results/ # 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/ # ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'), path('<int:question_id>/vote/', views.vote, name='vote'),
] ]

View File

@ -2,21 +2,25 @@ from django.http import request, HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.template import loader from django.template import loader
from django.urls import reverse from django.urls import reverse
from django.views import generic
from .models import Question, Choice from .models import Question, Choice
def index(request): class IndexView(generic.ListView):
latest_question_list = Question.objects.order_by('-pub_date')[:5] template_name = 'polls/index.html'
context = {'latest_question_list': latest_question_list} context_object_name = 'latest_question_list'
return render(request, 'polls/index.html', context)
def detail(request, question_id): def get_queryset(self):
question = get_object_or_404(Question, pk=question_id) """Return the last five published questions."""
return render(request, 'polls/detail.html', {'question': question}) return Question.objects.order_by('-pub_date')[:5]
def results(request, question_id): class DetailView(generic.DetailView):
question = get_object_or_404(Question, pk=question_id) model = Question
return render(request, 'polls/results.html', {'question': question}) template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def vote(request, question_id): def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id) question = get_object_or_404(Question, pk=question_id)