Python Django入门(创建其他网页)

news2025/3/22 9:19:01

在本章中,你将学习如何使用
Django(http://djangoproject.com/ )来开发一个名为“学习笔记”(Learning Log)的项目,这是一个在线日志系统,让你能够记录所学习的有关特定主题的知识。
我们将为这个项目制定规范,然后为应用程序使用的数据定义模型。我们将使用Django的管理系统来输入一些初始数据,再学习编写视图和模板,让Django能够为我们
的网站创建网页。
Django是一个Web框架 ——一套用于帮助开发交互式网站的工具。Django能够响应网页请求,还能让你更轻松地读写数据库、管理用户等。

创建其他网页

制定创建网页的流程后,可以开始扩充“学习笔记”项目了。我们将创建两个显示数据的网页,其中一个列出所有的主题,另一个显示特定主题的所有条目。对于每个网页,我们
都将指定URL模式,编写一个视图函数,并编写一个模板。但这样做之前,我们先创建一个父模板,项目中的其他模板都将继承它。

模板继承

创建网站时,几乎都有一些所有网页都将包含的元素。在这种情况下,可编写一个包含通用元素的父模板,并让每个网页都继承这个模板,而不必在每个网页中重复定义这些通
用元素。这种方法能让你专注于开发每个网页的独特方面,还能让修改项目的整体外观容易得多。

父模板

我们首先来创建一个名为base.html的模板,并将其存储在index.html所在的目录中。这个文件包含所有页面都有的元素;其他的模板都继承base.html。当前,所有页面都包含的元素
只有顶端的标题。我们将在每个页面中包含这个模板,因此我们将这个标题设置为到主页的链接:

<p>
❶ <a href="{% url 'learning_logs:index' %}">Learning Log</a>
</p>
❷ {% block content %}{% endblock content %}

这个文件的第一部分创建一个包含项目名的段落,该段落也是一个到主页的链接。为创建链接,我们使用了一个模板标签 ,它是用大括号和百分号({% %} )表示的。模板标
签是一小段代码,生成要在网页中显示的信息。在这个实例中,模板标签{% url ‘learning_logs:index’ %} 生成一个URL,该URL与learning_logs/urls.py中定义的名
为index 的URL模式匹配(见❶)。在这个示例中,learning_logs 是一个命名空间 ,而index 是该命名空间中一个名称独特的URL模式。
在简单的HTML页面中,链接是使用锚 标签定义的:

<a href="link_url">link text</a>

让模板标签来生成URL,可让链接保持最新容易得多。要修改项目中的URL,只需修改urls.py中的URL模式,这样网页被请求时,Django将自动插入修改后的URL。在我们的项目
中,每个网页都将继承base.html,因此从现在开始,每个网页都包含到主页的链接。

在❶处,我们插入了一对块标签。这个块名为content ,是一个占位符,其中包含的信息将由子模板指定。
子模板并非必须定义父模板中的每个块,因此在父模板中,可使用任意多个块来预留空间,而子模板可根据需要定义相应数量的块。

注意  在Python代码中,我们几乎总是缩进四个空格。相比于Python文件,模板文件的缩进层级更多,因此每个层级通常只缩进两个空格。

子模板

现在需要重新编写index.html,使其继承base.html,如下所示:

❶ {% 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 %}

如果将这些代码与原来的index.html进行比较,可发现我们将标题Learning Log替换成了从父模板那里继承的代码(见❶)。子模板的第一行必须包含标签{% extends %} ,让
Django知道它继承了哪个父模板。文件base.html位于文件夹learning_logs中,因此父模板路径中包含learning_logs。这行代码导入模板base.html的所有内容,让index.html能够指定要
在content 块预留的空间中添加的内容。

在❷处,我们插入了一个名为content 的{% block %} 标签,以定义content 块。不是从父模板继承的内容都包含在content 块中,在这里是一个描述项目“学习笔记”的
段落。在❸处,我们使用标签{% endblock content %} 指出了内容定义的结束位置。

模板继承的优点开始显现出来了:在子模板中,只需包含当前网页特有的内容。这不仅简化了每个模板,还使得网站修改起来容易得多。要修改很多网页都包含的元素,只需在
父模板中修改该元素,你所做的修改将传导到继承该父模板的每个页面。在包含数十乃至数百个网页的项目中,这种结构使得网站改进起来容易而且快捷得多。

注意  在大型项目中,通常有一个用于整个网站的父模板——base.html,且网站的每个主要部分都有一个父模板。每个部分的父模板都继承base.html,而网站的每个网
页都继承相应部分的父模板。这让你能够轻松地修改整个网站的外观、网站任何一部分的外观以及任何一个网页的外观。这种配置提供了一种效率极高的工作方式,
让你乐意不断地去改进网站。

显示所有主题的页面

有了高效的网页创建方法,就能专注于另外两个网页了:显示全部主题的网页以及显示特定主题中条目的网页。所有主题页面显示用户创建的所有主题,它是第一个需要使用数
据的网页。

URL模式

首先,我们来定义显示所有主题的页面的URL。通常,使用一个简单的URL片段来指出网页显示的信息;我们将使用单词topics,因此URL http://localhost:8000/topics/将返回显示所有
主题的页面。下面演示了该如何修改learning_logs/urls.py:

"""为learning_logs定义URL模式"""
--snip--
urlpatterns = [
# 主页
url(r'^$', views.index, name='index'),
# 显示所有的主题
❶ url(r'^topics/$', views.topics, name='topics'),
]

我们只是在用于主页URL的正则表达式中添加了topics/ (见❶)。Django检查请求的URL时,这个模式与这样的URL匹配:基础URL后面跟着topics 。可以在末尾包含斜
杠,也可以省略它,但单词topics 后面不能有任何东西,否则就与该模式不匹配。其URL与该模式匹配的请求都将交给views.py中的函数topics() 进行处理。

视图

函数topics() 需要从数据库中获取一些数据,并将其发送给模板。我们需要在views.py中添加的代码如下:

from django.shortcuts import render
❶ from .models import Topic
def index(request):
--snip--
❷ def topics(request):
"""显示所有的主题"""
❸ topics = Topic.objects.order_by('date_added')
❹ context = {'topics': topics}
❺ return render(request, 'learning_logs/topics.html', context)

我们首先导入了与所需数据相关联的模型(见❶)。函数topics() 包含一个形参:Django从服务器那里收到的request 对象(见❷)。在❸处,我们查询数据库——请求提
供Topic 对象,并按属性date_added 对它们进行排序。我们将返回的查询集存储在topics 中。

在❹处,我们定义了一个将要发送给模板的上下文。上下文是一个字典,其中的键是我们将在模板中用来访问数据的名称,而值是我们要发送给模板的数据。在这里,只有一个
键—值对,它包含我们将在网页中显示的一组主题。创建使用数据的网页时,除对象request 和模板的路径外,我们还将变量context 传递给render() (见❺)。

模板

显示所有主题的页面的模板接受字典context ,以便能够使用topics() 提供的数据。请创建一个文件,将其命名为topics.html,并存储到index.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 %}

就像模板index.html一样,我们首先使用标签{% extends %} 来继承base.html,再开始定义content 块。这个网页的主体是一个项目列表,其中列出了用户输入的主题。在标准
HTML中,项目列表被称为无序列表,用标签

    表示。包含所有主题的项目列表始于❶处。

    在❷处,我们使用了一个相当于for 循环的模板标签,它遍历字典context 中的列表topics 。模板中使用的代码与Python代码存在一些重要差别:Python使用缩进来指出哪些
    代码行是for 循环的组成部分,而在模板中,每个for 循环都必须使用{% endfor %} 标签来显式地指出其结束位置。因此在模板中,循环类似于下面这样:

    {% for item in list %}
    do something with each item
    {% endfor %}
    

    在循环中,我们要将每个主题转换为一个项目列表项。要在模板中打印变量,需要将变量名用双花括号括起来。每次循环时,❸处的代码{{ topic }} 都被替换为topic 的当
    前值。这些花括号不会出现在网页中,它们只是用于告诉Django我们使用了一个模板变量。HTML标签

    • 表示一个项目列表项,在标签对
        内部,位于标
      • 之间的内容都是一个项目列表项。

        在❹处,我们使用了模板标签{% empty %} ,它告诉Django在列表topics 为空时该怎么办:这里是打印一条消息,告诉用户还没有添加任何主题。最后两行分别结束for 循
        环(见❺)和项目列表(见❻)。

        现在需要修改父模板,使其包含到显示所有主题的页面的链接:

        <p>
        ❶ <a href="{% url 'learning_logs:index' %}">Learning Log</a> -
        ❷ <a href="{% url 'learning_logs:topics' %}">Topics</a>
        </p>
        {% block content %}{% endblock content %}
        

        我们在到主页的链接后面添加了一个连字符(见❶),然后添加了一个到显示所有主题的页面的链接——使用的也是模板标签url (见❷)。这一行让Django生成一个链接,它
        与learning_logs/ urls.py中名为topics 的URL模式匹配。
        现在如果你刷新浏览器中的主页,将看到链接Topics。单击这个链接,将看到类似于图18-4所示的网页。

        image

        显示特定主题的页面

        接下来,我们需要创建一个专注于特定主题的页面——显示该主题的名称及该主题的所有条目。同样,我们将定义一个新的URL模式,编写一个视图并创建一个模板。我们还将
        修改显示所有主题的网页,让每个项目列表项都是一个链接,单击它将显示相应主题的所有条目。

        URL模式

        显示特定主题的页面的URL模式与前面的所有URL模式都稍有不同,因为它将使用主题的id 属性来指出请求的是哪个主题。例如,如果用户要查看主题Chess(其id 为1)的详细
        页面,URL将为http://localhost:8000/topics/1/。下面是与这个URL匹配的模式,它包含在learning_logs/urls.py中:

        --snip--
        urlpatterns = [
        --snip--
        # 特定主题的详细页面
        url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
        ]
        

        我们来详细研究这个URL模式中的正则表达式——r’^topics/(?P<topic_id>\d+)/$’ 。r 让Django将这个字符串视为原始字符串,并指出正则表达式包含在引号内。这个
        表达式的第二部分(/(?P<topic_id>\d+)/ )与包含在两个斜杠内的整数匹配,并将这个整数存储在一个名为topic_id 的实参中。这部分表达式两边的括号捕获URL中的
        值;?P<topic_id> 将匹配的值存储到topic_id 中;而表达式\d+ 与包含在两个斜杆内的任何数字都匹配,不管这个数字为多少位。

        发现URL与这个模式匹配时,Django将调用视图函数topic() ,并将存储在topic_id 中的值作为实参传递给它。在这个函数中,我们将使用topic_id 的值来获取相应的主
        题。

        视图

        函数topic() 需要从数据库中获取指定的主题以及与之相关联的所有条目,如下所示:

        --snip--
        ❶ 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_logs/topic.html', context)
        

        这是第一个除request 对象外还包含另一个形参的视图函数。这个函数接受正则表达式(?P<topic_id>\d+) 捕获的值,并将其存储到topic_id 中(见❶)。在❷处,我
        们使用get() 来获取指定的主题,就像前面在Django shell中所做的那样。在❸处,我们获取与该主题相关联的条目,并将它们按date_added 排序:date_added 前面的减号
        指定按降序排列,即先显示最近的条目。我们将主题和条目都存储在字典context 中(见❹),再将这个字典发送给模板topic.html(见❺)。

        注意  ❷处和❸处的代码被称为查询,因为它们向数据库查询特定的信息。在自己的项目中编写这样的查询时,先在Django shell中进行尝试大有裨益。相比于编写视
        图和模板,再在浏览器中检查结果,在shell中执行代码可更快地获得反馈。

        模板

        这个模板需要显示主题的名称和条目的内容;如果当前主题不包含任何条目,我们还需向用户指出这一点:

        {% 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 %}
        

        像这个项目的其他页面一样,这里也继承了base.html。接下来,我们显示当前的主题(见❶),它存储在模板变量{{ topic }} 中。为什么可以使用变量topic 呢?因为它包
        含在字典context 中。接下来,我们开始定义一个显示每个条目的项目列表(见❷),并像前面显示所有主题一样遍历条目(见❸)。

        每个项目列表项都将列出两项信息:条目的时间戳和完整的文本。为列出时间戳(见❹),我们显示属性date_added 的值。在Django模板中,竖线(| )表示模板过滤器——
        对模板变量的值进行修改的函数。过滤器date: ‘M d, Y H:i’ 以这样的格式显示时间戳:January 1, 2015 23:00。接下来的一行显示text 的完整值,而不仅仅是entry 的前
        50个字符。过滤器linebreaks (见❺)将包含换行符的长条目转换为浏览器能够理解的格式,以免显示为一个不间断的文本块。在❻处,我们使用模板标签{% empty %} 打
        印一条消息,告诉用户当前主题还没有条目。

        将显示所有主题的页面中的每个主题都设置为链接

        在浏览器中查看显示特定主题的页面前,我们需要修改模板topics.html,让每个主题都链接到相应的网页,如下所示:

        --snip--
        {% for topic in topics %}
        <li>
        <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
        </li>
        {% empty %}
        --snip--
        

        我们使用模板标签url 根据learning_logs中名为topic 的URL模式来生成合适的链接。这个URL模式要求提供实参topic_id ,因此我们在模板标签url 中添加了属性topic.id
        。现在,主题列表中的每个主题都是一个链接,链接到显示相应主题的页面,如http://localhost:8000/topics/1/。
        如果你刷新显示所有主题的页面,再单击其中的一个主题,将看到类似于下图所示的页面。

        image

      本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2319473.html

      如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

      相关文章

      Error: The resource name must start with a letter

      Error: The resource name must start with a letter 这个错误通常是由于资源名称&#xff08;如布局文件、字符串资源、ID 等&#xff09;不符合命名规则导致的。Android 资源名称必须遵循以下规则&#xff1a; 必须以字母开头&#xff08;不能以数字或下划线开头&#xff09…

      2025年- G23-Lc97-104.二叉树的最大深度-java版(递归调用左右子树)

      1.题目描述 2.思路 要用到max函数&#xff0c;返回的时候返回左右子树的最大值。其次要递归调用左右子树&#xff0c;寻找最大深度。 在每个递归返回时&#xff0c;我们 必须把当前节点的深度算进去&#xff0c;否则我们只计算了子树的深度&#xff0c;而没有包括当前节点。 …

      Powershell WSL Windows系统复制数据到ubuntu子系统系统

      从本地D盘下拷贝数据到ubuntu子系统下 Powershell 管理员打开执行 /mnt/d 此处是本地Windows系统的路径表示/opt ubutu 子系统目录 wsl -d Ubuntu-22.04 -u root -- bash -c cp -rf /mnt/d/nginx.conf /opt/从ubuntu子系统中拷贝数据到本地D盘下 Powershell 管理员打开执行…

      到底爱不爱我

      L2-3 到底爱不爱我 古代少女有了心上人时&#xff0c;会悄悄折一条树枝&#xff0c;揪那枝上的叶子&#xff0c;揪一片叶子念一句“爱我”&#xff0c;再揪一片念一句“不爱我”…… 这样揪落最后一片叶子的时候&#xff0c;看看是停在“爱”还是“不爱”。 但聪明的慧娘一眼洞…

      Python 3.13.2安装教程(安装包)Python 3.13.2 快速安装指南

      文章目录 前言一 、Python 3.13.2下载二、Python 3.13.2安装教程1.运行安装程序2.选择安装方式3.自定义安装选项4.开始安装5.安装完成6.打开程序7.验证安装 前言 Python 作为一门通用编程语言&#xff0c;在全球拥有庞大的用户群体。其简洁易读的语法和丰富的库&#xff0c;使…

      Linux驱动学习笔记(六)

      平台总线 1.平台总线模型也叫platform总线模型&#xff0c;平台总线是Linux系统虚拟出来的总线, 引入总线的概念可以对驱动代码和设备信息进行分离。平台总线模型将一个驱动分成了两个部分&#xff1a;platform_device和platform_driver&#xff0c;例如可使用文件device.c和d…

      w264民族婚纱预定系统

      &#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

      Compose 实践与探索十五 —— 自定义触摸

      1、自定义触摸与一维滑动监测 之前我们在讲 Modifier 时讲过如下与手势检测相关的 Modifier&#xff1a; Modifier.clickable { } Modifier.combinedClickable { } Modifier.pointerInput {detectTapGestures { } }这里对以上内容就不再赘述了&#xff0c;直接去讲解更复杂的…

      炫酷的3D按钮效果实现 - CSS3高级特性应用

      炫酷的3D按钮效果实现 - CSS3高级特性应用 这里写目录标题 炫酷的3D按钮效果实现 - CSS3高级特性应用项目介绍核心技术实现1. 基础结构设计2. 视觉效果实现2.1 背景渐变2.2 立体感营造 3. 交互动效设计3.1 悬停效果3.2 按压效果 技术要点分析1. 深度层次感2. 动画过渡3. 性能优…

      teaming技术

      一.介绍 在CentOS 6与RHEL 6系统中&#xff0c;双网卡绑定采用的是bonding技术。到了CentOS 7&#xff0c;不仅能继续沿用bonding&#xff0c;还新增了teaming技术。在此推荐使用teaming&#xff0c;因其在查看与监控方面更为便捷 。 二.原理 这里介绍两种最常见的双网卡绑定…

      【JavaEE进阶】Linux常用命令

      目录 &#x1f343;前言 &#x1f334;pwd 与 ls &#x1f6a9;pwd &#x1f6a9;ls &#x1f38d;cd &#x1f332;mkdir与touch &#x1f6a9;mkdir &#x1f6a9;touch &#x1f340;cat与rm &#x1f6a9;cat &#x1f6a9;rm &#x1f38b;vim &#x1f6a9;…

      【FastGPT】利用知识库创建AI智能助手

      【FastGPT】利用知识库创建AI智能助手 摘要创建知识库上传文档创建应用准备提示词准备开场白关联知识库AI回答效果 摘要 关于FastGPT的部署&#xff0c;官方提供了docker-compose方式的部署文档&#xff0c;如果使用的是podman和podman-compose的同学&#xff0c;可以参考这篇…

      【DeepSeek 学c++】dynamic_cast 原理

      用于向下转化。 父类引用指向指类对象 假设父亲是a, 子类是b. B* pb new B; 子类对象 A* pa 父类引用指向子类对象&#xff0c; 那么向上转化 Apa pb 这个是自动完成的&#xff0c;隐式转化&#xff0c;不需要dynamic_cast 向下转化指的是 A pa new B。 这个是指向子类对象…

      【递归,搜索与回溯算法篇】- 名词解释

      一. 递归 1. 什么是递归&#xff1f; 定义&#xff1a; 函数自己调用自己的情况关键点&#xff1a; ➀终止条件&#xff1a; 必须明确递归出口&#xff0c;避免无限递归 ➁子问题拆分&#xff1a; 问题需能分解成结构相同的更小的子问题缺点&#xff1a; ➀栈溢出风险&#x…

      Beans模块之工厂模块注解模块@Qualifier

      博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

      数据结构---图的深度优先遍历(DFS)

      一、与树的深度优先遍历之间的联系 1.类似于树的先根遍历。 递归访问各个结点&#xff1a; 2.图的深度优先遍历 先设置一个数组&#xff0c;初始值全部设置为false&#xff0c;先访问一个结点&#xff0c;在用一个循环&#xff0c;依次检查和这个结点相邻的其他结点&#xff0c…

      健康养生:拥抱生活,从呵护身心开始

      在这个瞬息万变的时代&#xff0c;人们好似不停旋转的陀螺&#xff0c;在忙碌中迷失了对健康的关注。然而&#xff0c;健康养生绝非可有可无的点缀&#xff0c;它是幸福生活的基石&#xff0c;如同阳光与空气&#xff0c;滋养并支撑着我们的生命。当我们懂得拥抱健康养生&#…

      QT网页显示的几种方法及对比

      一.直接跳转打开网页 1.使用QDesktopServices::openUrl调用系统浏览器 原理&#xff1a;直接调用操作系统默认浏览器打开指定URL&#xff0c;不在应用程序内嵌入网页。 优点&#xff1a; 实现简单&#xff0c;无需额外模块或依赖。 适用于仅需跳转外部浏览器的场景。 缺点&…

      Linux python 安装 conda(内部自带的有python的版本了)

      位置网站 https://repo.anaconda.com/miniconda/也可以在https://www.anaconda.com/download/success 官方下载之后方linux中 切换路径之后 执行 bash Miniconda3-py310_25.1.1-2-Linux-x86_64.sh [rootVM-4-5-centos ~]# [rootVM-4-5-centos ~]# uname -a Linux VM-4-5-cen…

      git原理与常用命令及其使用

      认识工作区、暂存区、版本库 ⼯作区&#xff1a;是在电脑上你要写代码或⽂件的⽬录。 暂存区&#xff1a;英⽂叫 stage 或 index。⼀般存放在 .git ⽬录下的 index ⽂件&#xff08;.git/index&#xff09;中&#xff0c;我们 把暂存区有时也叫作索引&#xff08;index&#xf…