4.2 use generic views
parent
e0267685cc
commit
c7cb960daa
|
@ -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
|
|
@ -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'),
|
||||
]
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue