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