18.4.1模板继承
1.父模板
在index.html的目录中创建一个名为base.html的父模板,让每个网页都继承这个模板,而不必在没有网页中都重复修改这些通用元素。目前每个网页中都只有顶端的标题。
base.html
<p>
<!--模板标签,由大括号和百分号表示,生成要在网页中显示的信息。本例中{% url 'learning_logs:index' %}生成一个URL,与learning_logs/urls.py中定义名为index的URl模式匹配。-->
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
</p>
<!--块标签,内容由子模块指定-->
{% block content %}{% endblock content %}
2.子模板
现在重新编写index.html,使其继承base.html
index.html
<!--标签{% extends %}让Django知道它继承了"learning_logs/base.html"这个父模板-->
{% extends "learning_logs/base.html" %}
<!--定义父模板中预留块标签-->
{% block content %}
<p>Learning Log</p>
<p>Learning Logs helps you keep trace of your learning,just keep doing it!</p>
{% endblock content %}
18.4.2显示所有主题的页面
1.URL模式
我们首先定义显示所有主题页面的URL:http://localhost:8000/topics/将返回显示所有主题的页面。
urls.py
'''define the url pattern of learning_logs'''
from django.conf.urls import url
from . import views
urlpatterns = [
#homepage
url(r'^$',views.index,name='index'),
#show all topics
url(r'^topics/$',views.topics,name='topics'),
]
(#show all topics)URL的匹配模式:基础的URL后面跟着topics,可以在末尾添加斜杠,也可以忽略,否则不匹配,匹配之后将会交给views.py中的函数topics()进行处理。
2.视图
views.py
from django.shortcuts import render
from .models import Topic
# Create your views here.
def index(request):
--snip--
def topics(request): #django从服务器那里收到request对象
#show all the topics
#查询数据库,请求提供Topic对象,并且按照属性的date_added对他们排序,返回结果存储在topics
topics = Topic.objects.order_by('date_added')
context = {'topics': topics} #定义一个发给模板的上下文(字典)
return render(request,'learning_logs/topics.html',context)
3.模板
显示所有主题的页面接受字典context,以便能够使用topics()提供的数据。创建一个文件topics.html,存储到index.html的目录下。
topics.html
<!--继承父模板-->
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<!--项目列表用<ul><ul/>表示-->
<ul>
{% for topic in topics %}
<!--位于标签<li><li/>是一个列表项-->
<li>
<!--要在模块中打印变量,要将变量名用双花括号括起来-->
<a href="{% url 'learning_logs:topic' topic.id %}">{{topic}}</a>
</li>
{% empty %}
<li>No topics has been added yet.</li>
<!--指出for循环的结束点-->
{% endfor %}
</ul>
{% endblock content %}
现在需要修改父模板,使其包含到显示所有主题的页面的链接。
base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
<!--生成一个链接,与learning_logs/urls.py中名为topics的URL模式匹配-->
<a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>
{% block content %}{% endblock content %}
18.4.3显示特定主题的页面
1.URL模式
当我们想要查看主题为Chess的详细页面时,URl将为http://localhost:8000/topics/1/,所以我们要设置和它匹配的URL模式。
learning_logs/urls.py
'''define the url pattern of learning_logs'''
from django.conf.urls import url
from . import views
urlpatterns = [
#homepage
url(r'^$',views.index,name='index'),
#show all topics
url(r'^topics/$',views.topics,name='topics'),
#show more specific content of the page
url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name ='topic'),
]
表达式/(?P<topic_id>\d+)/与包含在两个斜杆内的任何数字匹配,?P<topic_id>将匹配的值存储到topic_id中。
当URL模式与其匹配时,Django将调用视图函数topic(),并将存储在topic_id的值作为实参传递给它。
2.视图
函数topic()需要从数据库获取指定的主题以及与之相关联的所有条目。
views.py
from django.shortcuts import render
from .models import Topic
# Create your views here.
def index(request):
--snip--
def topics(request):
--snip--
def topic(request,topic_id):
#show single theme and it's all entries
#使用get()获取指定的主题
topic = Topic.objects.get(id = topic_id)
#获取主题相关的条目
entries = topic.entry_set.order_by('-date_added')
#按date_added排序,前面的-指定按降序排序
context = {'topic':topic,'entries':entries}
return render(request,'learning_logs/topic.html',context)
3.模板
显示主题的名称和条目的内容;如果不包含任何条目,还需指出。
{% extends 'learning_logs/base.html' %}
{% block content %}
<p>Topic::{{topic}}</p>
<p>Entries:</p>
<ul>
{% for entry in entries %}
<li>
<!--其中的'|'表示模板过滤器,过滤器date:指定格式显示日期-->
<p>{{ entry.date_added|date:'M d,Y H:i'}}</p>
<!--过滤器linebreaks将包含换行符的长条目转换成浏览器能识别的格式-->
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>
There are no entries for this topic yet/
</li>
{% endfor %}
</ul>
{% endblock content %}
4.将显示所有主题的页面中的每个主题都设置为链接
--snip--
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{topic}}</a>
</li>
--snip--
我们使用模板标签url根据learning_logs中名为topic的URL模式来生成合适的链接。这个URL模式要求提供实参topic.id。