Django教程④(模板)
首先
在Django教程第3部分(创建模型、Django管理员)之后,尝试创建一个应用程序。在第一次创建Django应用程序时,参考《实用Django教程(基础篇)》,第3节。 (*请注意,在本文的后半部分中出现的视图图像取决于第二部分的“尝试玩API”,只有创建了名为“What’s up?”的问题以及与之关联的“Not much”和“The sky”选项,才会显示该图像。)
這是電腦轉換器的日文寫法。
按照教程的指示,在polls/views.py文件中添加一个视图函数,并在polls/urls.py中注册与该视图函数相关联的URLconf。
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)
from django.urls import path
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'),
]
重要的是在urls.py中所写的”。使用<>可以将URL的一部分作为关键字变量传递给视图函数。例如,如果有一个请求”/polls/34/”,detail函数将以question_id参数接收34。这是一种路径转换器的语法,Django提供了5种转换器:”int,str,path,slug,uuid”,也可以自定义转换器。
DTL(Django模板语言)
Django使用了一个名为DTL的模板系统,可以实现变量显示、过滤器、模板标签等功能。关于有哪些内容的详细信息,请参阅官方文档。
到目前为止,我们处理的视图函数在编码中也涉及了设计部分(虽然这里的设计只是将字符串排列起来)。因此,如果要更改页面设计,就必须编辑Python代码。因此,可以使用DTL将设计与Python代码分离。
首先,要设置config/settings.py中的TEMPLATES。只需要修改DIRS设置即可,其余设置保持默认不变。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
-
- BACKEND : テンプレートエンジンを設定する。デフォルト以外にも Jinja2 などを設定できるらしい。Jinja2 の方が機能が豊富ということも聞いたが、ここは一旦デフォルトのままで Django に慣れてきたら試したい。
-
- DIRS : どのディレクトリを優先してテンプレートを探しに行くかという順番を指定する。デフォルトでは [(空白)] だが、ここでは上記のように [os.path.join(BASE_DIR, ‘templates’)] としておく。(import os を忘れずに。)設定を変えた理由は後述。
-
- APP_DIRS : テンプレートを探す際に各アプリケーションディレクトリ直下の templates ディレクトリを優先的に探しにいくかどうかを設定する。デフォルトでは True 。
- OPTIONS : 正直あんまりよくわからない。わかる人教えてください。上記コードはデフォルトのまま。
在这里解释更改 DIRS 设置的原因。在教程中,创建了名为 polls/templates/polls 的目录,并在其中创建了模板 index.html,保持了默认设置。这种结构显然不清晰,而且根据以下教程中的原因,不需要在 polls/templates 目录下创建 polls 子目录才是适当的。
创建模板的命名空间
您可能会想,为什么不直接将自己创建的模板放在polls/templates中,而不是创建另一个名为polls的子目录呢。但是,实际上这是一个不好的想法。Django会使用与名称匹配的第一个模板,所以如果不同的应用程序中有相同名称的模板,Django将无法区分它们。因此,您需要告诉Django正确的模板,而最简单的方法就是为它们提供命名空间。通过将模板放在另一个具有相同名称的目录中,与应用程序相同的名称,这就是这么做的原因。
为了使目录结构更加清晰易懂,我们在基本目录下创建了一个templates目录,并将每个应用程序的模板作为其子目录处理。以下是实际的结构示例:
为了使目录结构更加清晰易懂,我们在基本目录下创建了一个templates目录,并将每个应用程序的模板作为其子目录处理。以下是实际的结构示例:
mysite (<- ベースディレクトリ)
|-- manage.py
|-- config (<- 設定ディレクトリ)
| |-- __init__.py
| |-- asgi.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
|-- polls (<- アプリケーション)
| |-- __init__.py
| |-- admin.py
| |-- apps.py
| |-- migrations
| | `-- __init__.py
| |-- models.py
| |-- tests.py
| `-- views.py
`-- templates (<- テンプレート)
`-- polls
`-- index.html
通过这样的配置,我们可以清晰明了地从基础目录中统一管理每个应用程序的模板。出于这个原因,我们改变了DIRS的设置。你可能会问:”如果采用这个配置,APP_DIRS应该不应该设置为False,优先搜索每个应用程序目录下的templates吗?” 然而,如果这样设置,可能会导致找不到管理网站的模板等问题,所以我们仍然将其设置为True。(如果想尝试,请在开发服务器上将 ‘APP_DIRS’ 设置为False,然后访问 http://localhost:8000/admin/,您将会看到错误信息。)
顺便提一下,有关 admin 的模板可以在 django/contrib/admin/templates/admin 目录下找到。要知道 django 源文件的位置,可以使用 $ python -c “import django; print(django.__path__)” 命令。
创建模板
在创建模板之前,需要修改polls/views.py文件中的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对象。
在templates/polls文件夹的根目录下创建一个名为index.html的文件,并编写以下代码。代码中的latest_question_list是在polls/views.py中指定的上下文键的名称,它表示与该键对应的变量。
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
以上的代码是用DTL语法编写的。用{% %}括起来的部分是模板标签,提供了方便的模板标签,如{% if (条件分支) %}或{% for (循环) %}等。在这里,如果latest_question_list存在,则以列表形式显示与其数量相对应的内容,如果不存在,则显示”No polls are available.”。此外,a标签内的href可以硬编码为
这样的链接部分,但由于URL的更改会变得混乱,因此在这里使用了{% url %}这个模板标签。这个模板标签可以通过在polls.urls.py中使用path()函数定义的URL进行反向解析。以下是本文开头提到的polls/urls.py的内容。
from django.urls import path
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 %} 的第一个参数是 URL 的模式名([app_name]:[path_name]),第二个参数及之后用于指定值以匹配该模式,如果正则表达式组包含在模式中。换句话说,对于
这种情况,它引用了在上述 polls/urls.py 文件中注册的 detail 路径的 ‘/’。这样一来,如果要更改 URL 模式,只需更改 polls/urls.py 文件,而无需更改模板。尽管可以不使用 app_name 来引用,但当应用程序变得复杂时,最好通过 app_name 来定义命名空间,以便在存在同名视图的情况下不会出现问题。
404错误
除了返回与请求对应的 HttpResponse 对象,视图还承担着返回异常的角色。在这里,我们将在显示指定投票问题的 detail 视图中实现异常处理。请将以下代码添加到 polls/views.py 中。
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并写入以下代码。get_object_or_404()函数执行get(),如果对象不存在,则引发Http404错误。
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
最后
多亏了实用的《Django实战教程(基础篇)》,我的理解有所提升。这本书很好。接下来,我会继续进行《初识Django应用开发》的第4章。
以下是相关文章的链接:
– Django教程①(安装和创建项目)
– Django教程②(创建视图)
– Django教程③(创建模型和使用Django Admin)
– Django教程⑤(通用视图)
– Django教程⑥(自动测试)
– Django教程⑦(静态文件)