用户通过在浏览器输入URL及单击链接来请求网页,因此我们要确定项目需要哪些URL。主页的URL最重要,当前基础的URL(http://127.0.0.1:8000/)返回默认的是Django网站。这里我们将基础的URL映射到“学习笔记”的主页。
打开项目主文件夹learning_log中的文件urls.py
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
前两行导入了为项目和管理网站管理URL的函数和模块
定义了变量urlpatterns ,变量urlpatterns 中包含项目中的应用程序的URL。
包含了模块admin.site.urls,该模块定义了可在管理网站中请求的所有URL。
我们需要包含learning_lops的URL:
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
#自己添加的URL 在learning_logs中的urls中
path('',include('learning_lops.urls',namespace='learning_lops')),
]
path(’’,include(‘learning_lops.urls’,namespace=‘learning_lops’))
包含了模块learning_lops.urls,还包含了实参namespace,让我们能够使learning_lops的URL同其他项目中的URL区分出来。
我们需要在learning_lops中创建另一个urls.py文件:
from django.urls import path
from . import views
app_name = 'learning_logs'
urlpatterns = [
#主页
path('', views.index, name='index'),
]
from django.urls import path
导入了函数path,需要使用它来将URL映射到视图
urlpatterns
变量urlpatterns是一个列表,包含可在应用程序learning_logs中请求的网页
效果图如图所示:
视图函数接收请求中的信息,准备好生成网页所需的数据,再将这些数据发给浏览器。
learning_lops中的文件views.py是这行python manage.py startapp时自动生成的
在views.py文件中修改创建视图
from django.shortcuts import render
# Create your views here.
def index(request):
"""学习笔记主页"""
return render(request,'learning_lops/index.html')
URL请求与我们刚才定义的模式匹配时,Django将在文件views.py中查找函数index(),再将请求对象传递给这个视图函数
模板定义了网页的结构,模板制定了网页是什么样子。
在learning_lops中新建一个文件夹命名为templates,在文件夹templates中,再新建一个文件夹learning_lops,在learning_lops夹中新建一个index.html文件。
index.html文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<P>hello world!</P>
<p>Learning Log</p>
<p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>
</body>
</html>
请求这个项目的基础URL http://127.0.0.1:8000/
将看到刚才创建的网页,而不是Django网页。
指定创建网页的流程后,可以扩充“学习笔记”项目了。我们将创建两个显示数据的网页,其中一个列出所有主题,另一个显示特定主题的所有条目。
对于每个网页,我们都将指定URL模式,编写一个视图函数,并编写一个模板。
在操作之前,我们需要先创建一个父模板,项目中的其他模板都将继承它。
创建网站时,几乎都有一些所有网页都将包含的元素。这边编写一个包含通用元素的父模板。并让每个网站都继承父模板
首先我们创建一个base.html的模板并将其存储在index.html所在的文件夹下。我们将在每个页面都包含这个模板因此我们将这个标题设置为到主页的链接。
在base.html文件中添加:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父模块</title>
</head>
<body>
<p>
<a href="{% url 'learning_lops:index' %}">Learning Log</a>
</p>
{% block content %}{% endblock content %}
</body>
</html>
{% %}
模板标签,模板标签是一小段代码,生成要在网页中显示的信息
{% block content %}{% endblock content %}
插入了一对标签这个块名为content,是一个占位符,其中包含的信息由子模块决定
现在我们要重新编写index.html,使其继承base.html
在index.html中修改
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主界面</title>
</head>
<body>
{% extends "learning_lops/base.html" %}
{% block content %}
<p>hello world!</p>
<p>学习日志可以帮助你跟踪你的学习,不管你在学什么。</p>
{% endblock content %}
</body>
</html>
{% extends %}
子模板的第一行必须包含标签{% extends %},让Django知道它继承了哪个模板
{% block content %}
让index.html能够指定要在content块预留的空间中添加内容
显示全部主题的网页以及显示特定主题中条目的网页。
首先,我们来定义显示所有主题页面的URL。
在learning_lops/urls.py文件中修改
from django.urls import path
from . import views
app_name = 'learning_logs'
urlpatterns = [
#主页
path('', views.index, name='index'),
#显示所有主题
path('topics/', views.topics, name='topics'),
]
path(‘topics/’, views.topics, name=‘topics’),
Django检查请求URL时,基础URL后面跟着topics,其URL与该模式匹配的请求都将交给views.py中的函数topics( )进行处理。
函数topics( )需要从数据库中获取一些数据,并将其发给模板。
在views.py中修改:
from django.shortcuts import render
from .models import Topic
def index(request):
"""学习笔记主页"""
return render(request,'learning_lops/index.html')
def topics(request):
"""Show all topics."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_lops/topics.html', context)
from .models import Topic
首先导入了与所需数据相关联的模型
def topics(request):
函数topics( )包含了一个形参,Django从服务器那里收到request对象。
topics = Topic.objects.order_by(‘date_added’)
我们查询数据库,请求提供Topic对象,并按照属性date_added对他们进行排序,将返回的查询集存储在topics 中
context = {‘topics’: topics}
我们定义了一个将要发送给模板的上下文。上下文是一个字典,其中的键是我们将在模板中用来访问数据的名称,而值是我们要发送给模板的数据。
return render(request, ‘learning_lops/topics.html’, )
创建使用数据的网站时,除了request和模板的路径外,我们还要将变量context传递给render( )
显示所有主题的页面的模板接受字典 context,以便能够使用topics( )提供的数据。
创建新的文件topics.html,并存储在topics.html目录下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Topics</title>
</head>
<body>
{% extends "learning_lops/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
{{ topic }}
</li>
{% empty %}
<li>尚未添加任何主题。</li>
{% endfor %}
</ul>
{% endblock content %}
</body>
</html>
{% for topic in topics %}
用了一个for循环的的模板标签,它遍历字典context 中的列表topics
{% endfor %}
每个for循环标签都必须使用{% endfor %}标签来指出循环结束的位置
{{ topic }}
{{ }}表示使用一个模板变量,被替换为topic的当前值
{% empty %}
告诉Django在列表topics为空的时候该怎么办
现在需要修改父模板,使其包含到显示所有主题的页面的链接:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父模块</title>
</head>
<body>
<p>
<a href="{% url 'learning_lops:index' %}">Learning Log</a> -
<a href="{% url 'learning_lops:topics' %}">Topics</a>
</p>
<p>一动不动是王八</p>
{% block content %}{% endblock content %}
</body>
</html>
刷新浏览器的主页后,将看到链接Topics,单词链接会显示出子模板
创建一个专注于特定主题的页面——显示该主题的名称及该主题的所有条目。同样我们将定义一个新的URL模式,编写一个视图并创建一个模板。我们还将修改显示所有主题的网页,让每个项目都是一个链接,单击它显示相应主题的所有条目。
显示特定页面的URL模式与前面的所有URL模式都稍有不同,因为它将使用主题的id属性 来指出请求的是哪个主题。
在learning_lops/urls.py中条件:
from django.urls import path
from . import views
app_name = 'learning_logs'
urlpatterns = [
#主页
path('', views.index, name='index'),
#显示所有主题
path('topics/', views.topics, name='topics'),
# 特定主题的详细页面
path('topics//' , views.topic, name='topic'),
]
函数topic( )需要从数据库中获取指定位置的主题以及与之相关联的所有条目。
在views.py文件中添加:
def topic(request, topic_id):
"""显示特定主题及其所有条目。"""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_lops/topic.html', context)
topic = Topic.objects.get(id=topic_id)
用get( )来获取指定的主题
entries = topic.entry_set.order_by(’-date_added’)
获取与该主题相关的条目,并按照date_added降序排序
context = {‘topic’: topic, ‘entries’: entries}
存储在字典中
模板需要显示主题的名称和条目的内容,如果当前主题不包括任何条目,则返回这个主题还没有条目。
新建文件topic.html文件,在index.html同文件夹下新建即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% extends 'learning_lops/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>这个主题还没有条目。</li>
{% endfor %}
</ul>
{% endblock content %}
</body>
</html>
{% extends ‘learning_lops/base.html’ %}
继承了父模板
{% block content %} {% endblock content %}
定义content 块
Topic: {{ topic }}
主题存储在{{ topic }}变量中,变量topic 包含在字典中
{% for entry in entries %}
遍历条目
{{ entry.date_added|date:‘M d, Y H:i’ }}
(|)表示模板过滤器,M月份 d日 Y年份 H小时 i分钟
{{ entry.text|linebreaks }}
显示text的完整值,而不仅仅是entry的前50个字符,过滤器linebreaks 将包含换行符的长条目转换为浏览器能够理解的格式,以免显示为一个不间断的文本。
在浏览器中查看显示特定主题的页面,我们需要修改模板topics.html,让每个主题都链接到相应的网页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Topics</title>
</head>
<body>
{% extends "learning_lops/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
<a href="{% url 'learning_lops:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
<li>尚未添加任何主题。</li>
{% endfor %}
</ul>
{% endblock content %}
</body>
</html>
{% url ‘learning_lops:topic’ topic.id %}
使用模板标签url根据learning_lops中名为topic的URL模式来生成合适的链接,这个URL模式要求提供实参 topic_id,因此我们在模板中添加了属性 topic.id。