内容太多了断个章接着记笔记…
编辑更多视图
让我们向 polls/views.py
中添加更多视图:
1 2 3 4 5 6 7 8 9 10 11
| def detail(request, question_id): return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id): response = "You're looking at the results of question %s." return HttpResponse(response % question_id)
def vote(request, question_id): return HttpResponse("You're voting on question %s." % question_id)
|
将这些视图添加进 polls.urls
模块里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from django.urls import path
from . import views
urlpatterns = [ path("", views.index, name="index"), path("<int:question_id>/", views.detail, name="detail"), path("<int:question_id>/results/", views.results, name="results"), path("<int:question_id>/vote/", views.vote, name="vote"), ]
|
之后我们若转到 /polls/34/
,Django 将会运行 detail()
方法并且展示你在 URL 里提供的问题 ID。
更好的视图
每个视图必须要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse 对象,或者抛出一个异常,比如 Http404 。
你的视图可以从数据库里读取记录,可以使用一个模板引擎(比如 Django 自带的,或者其他第三方的),可以生成一个 PDF 文件,可以输出一个 XML,创建一个 ZIP 文件,你可以做任何你想做的事,使用任何你想用的 Python 库。
让我们在在 index()
函数里插入一些新内容,让它能展示数据库里以发布日期排序的最近 5 个投票问题,以空格分割:
1 2 3 4 5 6 7 8 9 10 11 12
| from django.http import HttpResponse
from .models import Question
def index(request): latest_question_list = Question.objects.order_by("-pub_date")[:5] output = ", ".join([q.question_text for q in latest_question_list]) return HttpResponse(output)
|
这里有个问题:页面的设计写死在视图函数的代码里的。如果你想改变页面的样子,就需要编辑 Python 代码。所以让我们使用 Django 的模板系统,只要创建一个视图,就可以将页面的设计从代码中分离出来。
首先,在你的 polls 目录里创建一个 templates 目录。Django 将会在这个目录里查找模板文件。项目的 TEMPLATES 配置项描述了 Django 如何载入和渲染模板。默认的设置文件设置了 DjangoTemplates 后端,并将 APP_DIRS
设置成了 True
。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS
文件夹中寻找 “templates“ 子目录。这就是为什么尽管我们没有像在第二部分中那样修改 DIRS 设置,Django 也能正确找到 polls 的模板位置的原因。
在刚刚创建的 templates 目录里,再创建一个目录 polls,然后在其中新建一个文件 index.html
。
将以下代码输入到模版文件中:
1 2 3 4 5 6 7 8 9
| {% if latest_question_list %} <ul> {% for question in latest_question_list %} <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
|
然后,让我们更新一下 polls/views.py
里的 index 视图来使用模板:
1 2 3 4 5 6 7 8 9 10 11 12 13
| from django.http import HttpResponse from django.template import loader
from .models import Question
def index(request): latest_question_list = Question.objects.order_by("-pub_date")[:5] template = loader.get_template("polls/index.html") context = { "latest_question_list": latest_question_list, } return HttpResponse(template.render(context, request))
|
上述代码的作用是,载入 polls/index.html
模板文件,并且向它传递一个上下文(context)。这个上下文是一个字典,它将模板内的变量映射为 Python 对象。
render() 函数
「载入模板,填充上下文,再返回由它生成的 HttpResponse 对象」是一个非常常用的操作流程。于是 Django 提供了一个快捷函数,我们用它来重写 index()
视图:
1 2 3 4 5 6 7 8 9
| from django.shortcuts import render
from .models import Question
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)
|
抛出 404 错误
现在,来处理投票详情视图——它会显示指定投票的问题标题。下面是这个视图的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| from django.http import Http404 from django.shortcuts import render
from .models import Question
def detail(request, question_id): try: question = Question.objects.get(pk=question_id) except Question.DoesNotExist: raise Http404("Question does not exist") return render(request, "polls/detail.html", {"question": question})
|
现在,如果指定问题 ID 所对应的问题不存在,这个视图就会抛出一个 Http404 异常。
get_object_or_404() 函数
尝试用 get()
函数获取一个对象,如果不存在就抛出 Http404 错误也是一个普遍的流程。Django 也提供了一个快捷函数,下面是修改后的详情 detail()
视图代码:
1 2 3 4 5 6 7 8 9
| from django.shortcuts import get_object_or_404, render
from .models import Question
def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, "polls/detail.html", {"question": question})
|