使用通用视图
2022/1/9大约 2 分钟pythonweb框架
使用通用视图
目的
基于 Django 的通用视图可以减少自己视图的代码设计
重写视图
先看不用通用视图的代码,自己实现的视图,要传入请求,然后利用快捷函数 render 返回 HttpResponse
# Create your views here.
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from polls.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)
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})
django.views 里有个 generic, generic 里有 ListView 和 DetailView 分别实现了常用的列出对象,和对象详情的类,直接从这两个类继承定义自己的视图类,然后重写类属性,指定用到的模板文件。再然后:
- ListView 需要重写 context_object_name 传入模板的上下文对象
- DetailView 需要重写 model 来指定自己写的模型
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.
重写 url parttern
之前的 urls.py 里指定了传入视图的主键名称(int:question_id 里的 question_id 如下),对应之前实现的视图函数的参数
from django.urls import path
from . import views
app_name = 'polls' # 为下面的 url 添加一个命名空间
# 如有多个 urlpattern ,按顺序匹配 route
urlpatterns = [
# 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'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]
而新的视图里没有指定 url 传入的主键名,所以默认就规定都用 pk 这个 url 里的变量来统一代替
from django.urls import path
from . import views
app_name = 'polls' # 为下面的 url 添加一个命名空间
# 如有多个 urlpattern ,按顺序匹配 route
urlpatterns = [
# ex: /polls/
path('', views.IndexView.as_view(), name='index'),
# ex: /polls/5/
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
# ex: /polls/5/results/
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
总结
- 利用通用视图,让 urls.py 和 views.py 的代码逻辑减少,不用指定主键变量名,因为通用视图默认 pk
- 适合 对象列出,对象详情 这两种非常非常常用的数据检索行为
更多通用视图的文档
https://docs.djangoproject.com/zh-hans/4.0/topics/class-based-views/