这部分是关于如何用Django框架创建一个简单的polls app的第三部分,主要内容是关于如何创建公共界面——即“视图”(views)。
1.编写更多视图
在polls app中,我们将有以下四个视图:
问题“索引”页:显示最新的几个问题。
问题“详情”页:显示问题的文本,没有结果,但有一个投票表单。
问题“结果”页:显示特定问题的结果。
投票操作:处理对特定问题中特定选项的投票。
在Django中,网页和其他内容由视图提供。每个视图由一个Python函数(或类视图中的方法)表示。Django通过检查请求的URL(具体来说,是域名后的部分)来选择视图。
首先,在polls/views.py中添加几个视图,这些视图稍有不同,因为它们接受一个参数:
def detail(request, question_id):
return HttpResponse(f"You're looking at question {question_id}.")
def results(request, question_id):
response = f"You're looking at the results of question {question_id}."
return HttpResponse(response)
def vote(request, question_id):
return HttpResponse(f"You're voting on question {question_id}.")
将这些新视图连接到polls.urls模块,添加以下路径调用:
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/”,它将运行detail()函数并显示你在URL中提供的ID。尝试“/polls/34/results/”和“/polls/34/vote/”也会显示占位符结果和投票页面。
2. 实际工作的视图
每个视图负责返回一个包含请求页面内容的HttpResponse对象,或引发如Http404之类的异常。视图可以使用Django的数据库API,也可以不使用。这里是一个实际显示系统中最新5个投票问题的index()视图示例:
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的目录。然后在其中创建另一个名为polls的目录,并在其中创建一个名为index.html的文件。模板应该位于polls/templates/polls/index.html
。
使用模板系统
在polls/templates/polls/index.html中放入以下代码:
{% 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视图以使用模板:
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))
点击 What’s up, 可以看到:
Django还提供了一个快捷方式render(),可以简化加载模板、填充上下文并返回渲染模板的结果的过程。使用render()函数,我们可以重写index()视图:
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)
再次访问http://127.0.0.1:8000/polls/, 可以看到同样的效果:
3. 引发404错误
现在,开始处理显示给定投票问题文本的detail视图。如果请求的ID不存在,则视图会引发Http404异常:
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/index.html", {"question": question})
Django提供了一个快捷方式get_object_or_404(),可以简化这个过程:
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/index.html", {"question": question})
访问http://127.0.0.1:8000/polls/1/ 出现下图,即显示代码正常运行
4. 使用模板系统
在views文件中修改detail函数,把最后一行代码的 polls/index.html 改为polls/detail.html
给定上下文变量question,polls/detail.html模板可能如下所示:
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
模板系统使用点查找语法来访问变量属性。例如,{{ question.question_text }}首先在字典question上执行查找,如果失败,则尝试属性查找。如图:
5. 移除模板中的硬编码URL
在polls/index.html模板中,我们之前硬编码了一个问题的链接。为了不依赖于特定URL路径,可以使用{% url %}模板标签:
html
- {{ question.question_text }}
- 这种方式通过查找polls.urls模块中指定的URL定义来工作。 ![在这里插入图片描述](https://i-blog.****img.cn/direct/eee8a3f9116a432eb280033cc29b67aa.png) 验证代码是否正常进行: ![在这里插入图片描述](https://i-blog.****img.cn/direct/02fa5c3c3e794cf29a2b76e2f026e40e.png)
6. 命名空间URL名称
在实际的Django项目中,可能有多个应用。Django如何区分它们之间的URL名称?答案是添加命名空间到URLconf。在polls/urls.py文件中,设置应用命名空间:
app_name = "polls"
现在更改polls/index.html模板,指向命名空间的detail视图:
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
访问http://127.0.0.1:8000/polls,点击 What’s up, 可以看到:
参考链接:https://docs.djangoproject.com/en/5.1/intro/tutorial03/