python3.6
Django2.0.1
1. 模板继承
创建一个base.html,其他的模板都继承这个父模板。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <p> <a href="{% url 'learning_logs:index' %}">Learning Log</a> </p> {% block content %}{% endblock content %} </body> </html>
{% url 'learning_logs:index' %}
表示在命名空间learning_logs下的名为index的地址。
index是在/learning_logs/urls.py中的urlpatterns中定义的
{% block content %}{% endblock content %} 这是一个块标签, 表示一个名为content的块, 其中的内容需要由子模块指定。 可以在base.html中定义多个块,但是子模块可以只指定其中的一个或几个,不是必须全部指定。
现在重新编写index.html以继承base.html
原内容为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<p>Learning Log</p>
<p>Learning Log helps you keep track of your learning,
for any topic you're learning about.</p>
</body>
</html>
把
<p>Learning Log</p>
<p>Learning Log helps you keep track of your learning,
for any topic you're learning about.</p>
改为:
{% extends "learning_logs/base.html" %} {% block content %} <p>Learning Log helps you keep track of your learning, for any topic you're learning about.</p> {% endblock content %}
这样,父模板中的内容就被继承过来,其中
<p> <a href="{% url 'learning_logs:index' %}">Learning Log</a> </p>
将直接显示,
而
{% block content %}{% endblock content %}
需要子模板定义。
2. 添加页面
修改learning_logs/urls.py
"""define url mode of learning_logs"""
from django.urls import path, re_path
from . import views
urlpatterns = [
# home
path('', views.index, name='index'),
# topics
path('topics/', views.topics, name='topics'),
]
app_name = 'learning_logs'
添加了path('topics/', views.topics, name='topics'),
现在localhost:port/topics/得到了匹配,访问这个地址时,将调用views.py中的topics函数;在其他地方也可以引用别名topics来访问这个url
下面在视图views.py中导入Topic类,并创建topics函数:
from django.shortcuts import render
# import class "Topic" from ./models.py
from .models import Topic
# Create your views here.
def index(request):
"""home page of learning log"""
return render(request, 'learning_logs/index.html')
def topics(request):
"""show all topics"""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
context = {'topics': topics}
定义了一个上下文,它是一个字典。这个上下文马上会通过render
发送到learning_logs/topics.html
中,用于数据的操作。
下面创建topics.html
{% extends "learning_logs/base.html" %} {% block content %} <p>Topics</p> <ul> {% for topic in topics %} <li> {{ topic }} </li> {% empty %} <li>No topics have been added yet.</li> {% endfor %} </ul> {% endblock content %}
{% empty %}
表示:如果topics为空的话,如何处理
现在父模板base.html如下:
<p> <a href="{% url 'learning_logs:index' %}">Learning Log</a> </p> {% block content %}{% endblock content %}
目前只有主页的链接,下面添加topics页面的链接,使得任何一个继承base.html的页面,都显示指向主页index
和主题页topics
的链接,亦即localhost:port/
和localhost:port/topics
<p> <a href="{% url 'learning_logs:index' %}">Learning Log</a> - <a href="{% url 'learning_logs:topics' %}">Topics</a> </p> {% block content %}{% endblock content %}
以上实现了主题页的显示,该页列出所有主题,下面继续创建单个主题的页面,在这个页面中,将显示有关这个主题的所有话题。
现在要实现这样的访问,例如:
localhost:port/topics/1/
即访问主题id为1的主题。
为此,在learning_logs/urls.py中的urlpatterns中添加:
# specified topic detail
re_path('topics/(?P<topic_id>\d+)/', views.topic, name='topic'),
/(?P<topic_id>\d+)/
的两端是两个斜杠,举栗说,他们匹配localhost:port/topics/1/中的1,并且把1存储在topic_id中。
具体地,两边的括号()捕获url中的值,?P<topic_id>
把匹配的值存到topic_id中,\d+
表示匹配任何位数的数字。
如果url匹配了,django就调用views.py中的topic函数,并把topic_id中的值作为实参传递给它。
现在,创建视图函数topic()
在views.py
中添加:
def topic(request, topic_id):
"""show one topic with its all entry"""
topic = Topic.objects.get(id=topic_id)
# minus sign indicates descending sort
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
注意这个函数包含一个形参topic_id
, -date_added
前的减号表示降序排列,
把主题和条目都存在context字典中,
把上下文context
传递给topic.html
下面编写具体主题页的模板:
{% extends 'learning_logs/base.html' %} {% block content %} <p>Topic: {{ topic }}</p> <p>Entries</p> <ul> {% for entry in entries %} <li> <p>{{ entry.date_added|date:'M d, Y H:i' }}</p> <p>{{ entry.text|linebreaks }}</p> </li> {% empty %} <li> There are no entries for this topic yet. </li> {% endfor %} </ul> {% endblock content %}
<p>Topic: {{ topic }}</p>
中的topic
和{% for entry in entries %}
中的entries
来自context
上下文,是刚刚由render函数传递过来的。
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p> <p>{{ entry.text|linebreaks }}</p>
竖线|表示模板过滤器
最后,修改topics.html
,把{{ topic }}
修改为<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
让每个主题都成为链接,链接到相应的主题详情页面
{% extends "learning_logs/base.html" %} {% block content %} <p>Topics</p> <ul> {% for topic in topics %} <li> <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a> </li> {% empty %} <li>No topics have been added yet.</li> {% endfor %} </ul> <a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a> {% endblock content %}
然后输入http://localhost:8000
点击topic:
点击Chess:
点击Rock Climbing:
另外注意:当你修改内容的时候,先把终端关闭 ,然后重新启动 ,然后再刷新浏览器 , 不然会出现错误!