• 视图
视图其实是视图函数的简称,视图是Django应用程序中网页的“类型”,通常具有特定功能并具有特定模板。
在Django中,网页和其他内容是通过视图传递的。每个视图均由Python函数(或方法(对于基于类的视图而言))表示。Django将通过检查所请求的URL(准确地说,是域名之后的URL部分)来选择视图。
• URL
URL即统一资源定位符,是每一个信息资源都有统一的且在网上唯一的地址。
URLconfs即URL模式,是URL的一般形式Django提供了更加优雅的URL模式,例如:
/newsarchive/<year>/<month>/
• 添加更多的视图
更改views.py:
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.py:
from django.urls import path
from . import views
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地址,通过遍历的方式寻找匹配的URL模式串,并调用相对应的视图函数,相应相对应的网页。
比如说,当有人从网站请求页面时,例如“ / polls / 34 /”,Django将加载mysite.urls的Python模块,因为该ROOT_URLCONF设置指向该模块 。它找到名为的变量urlpatterns并按顺序遍历模式。在找到匹配项之后’polls/’,它将剥离匹配的文本(“polls/”),并将其余文本–发送 "34/"到’polls.urls’URLconf进行进一步处理。在那里匹配’int:question_id/’,从而导致对detail()视图的调用,如下所示:
detail(request=, question_id=34)
• 编写更强大的视图
每个视图负责执行以下两项操作之一:返回HttpResponse包含所请求页面内容的对象,或者引发诸如之类的异常Http404。
HttpResponse需要自己对其进行填充,而HttpRequest是Django自己生成。
视图可以从数据库中读取记录,也可以使用Django等模板系统,也可以不使用第三方Python模板系统。它还可以使用所需的任何Python库生成PDF文件,输出XML,或即时创建ZIP文件。
在view.py添加代码:
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)
# Leave the rest of the views (detail, results, vote) unchanged
• 将模板与视图创建的硬编码分开
首先,在目录templates中创建一个polls目录。Django将在那里寻找模板。
您的项目TEMPLATES置描述了Django如何加载和呈现模板。默认设置文件配置一个DjangoTemplates 后端,其APP_DIRS选项设置为 True。按照惯例DjangoTemplates,在每个文件夹中都会寻找一个“模板”子目录INSTALLED_APPS。
在*polls/templates/polls/*添加一个模板:
{% 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来加载一个“最新消息”列表。
• 快捷方式
加载模板,填充上下文并使用渲染后的模板的结果返回对象HttpResponse是一种非常常见的用法。
同时,Django提供了一种快捷方式。重写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)
该render()函数将请求对象作为其第一个参数,将模板名称作为其第二个参数,并将字典作为其可选的第三个参数。它返回使用HttpResponse 给定上下文呈现的给定模板的对象。
• 404错误
在views.py中添加代码:
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})
为了快速使示例正常工作,对应模板polls/templates/polls/detail.html
中只添加:
{{ question }}
现在运行服务器,可以看到更完整的polls网页
• 404的快捷方式
重写detail()函数:
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})
• 使用模板系统
polls/detail.html改写为:
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
模板系统使用点查找语法来访问变量属性。在的示例中,首先Django在对象上进行字典查找。如果失败,它将尝试属性查找-在这种情况下可以工作。如果属性查找失败,它将尝试进行列表索引查找。
• 命名空间URL名称
在实际的Django项目中,可能有很多个应用程序,Django如何区分它们之间的URL名称呢?答案是将名称空间添加到URLconf中。
在polls/urls.py中添加app_name以设置为应用程序名称空间:
from django.urls import pat
from . import views
app_name = 'polls'
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'),
]
这样可以区分多个应用程序的URL名称。